home *** CD-ROM | disk | FTP | other *** search
/ SPACE 1 / SPACE - Library 1 - Volume 1.iso / program / 386 / arpbook7 / chap_7.doc
Text File  |  1989-03-30  |  125KB  |  2,996 lines

  1.      Atari ST Machine Specific Programming In Assembly
  2.  
  3. Chapter 7: An Adaptive Algorithm
  4.      
  5.  
  6. Algorithmic Intelligence
  7.   
  8.      By saying to you now that I consider every item of 
  9. software to be intelligent to at least some degree, I 
  10. restrict the range of my future comments concerning any 
  11. comparisons between the levels of intelligence of items of 
  12. software to the extent that I will not be able to refer to 
  13. one item as intelligent and another as being devoid of 
  14. intelligence.  My comments would not be as restricted if 
  15. there were a system of intelligent quotients for software, 
  16. because then I would be able to assign an IQ to each item 
  17. under discussion in order to specify its relative level of 
  18. intelligence.
  19.      I am not aware of the existence of such a system and I 
  20. have no desire to develop one myself, at least not at this 
  21. time.  Therefore, in order to differentiate between levels 
  22. of software intelligence, I must use descriptive phrases 
  23. such as smarter than or more intelligent than.  I place 
  24. these limits on the terminology I permit myself to use in 
  25. this chapter because I want to avoid extensive, 
  26. nonproductive philosophical discussions of relative levels 
  27. of intelligence.
  28.      Most of the algorithms that I have discussed so far 
  29. have been designed to perform their functions in an 
  30. unsophisticated fashion, without much regard for external 
  31. stimuli.  Notable exceptions are the custom traps which 
  32. adjust their output based on the number of digits or the 
  33. number of leading zeroes in a passed parameter and trap #8, 
  34. which executes a wait for keypress algorithm only if the 
  35. invoking process was not spawned by another.  To the degree 
  36. that response to external stimuli is a measure of 
  37. intelligence, those custom traps which adapt their output 
  38. according to input are more intelligent than those which 
  39. simply alter a memory location, such as does trap #0, or 
  40. return a value, such as does trap #3.
  41.      Much as I have declared custom traps which alter their 
  42. output in response to their input to be the more intelligent 
  43. in the paragraph above, I shall simply declare that an 
  44. algorithm which can alter itself in response to external 
  45. stimuli to be more intelligent than one which cannot do so.  
  46. And, in order to reduce the length of descriptive phrases, I 
  47. shall refer to such algorithms as adaptive algorithms.  In 
  48. fact, I shall simply declare that the term adaptive applies 
  49. to any algorithm which can alter itself in response to any 
  50. stimuli, whether it be externally or internally generated.
  51.      If you have read the suggested material in Christopher 
  52. Evans' The Micro Millennium, I believe that you will grasp 
  53. my line of reasoning and deduce that I am laying the 
  54. foundation for a discussion of an item of software to which 
  55. Mr. Evans' six major constituents of intelligence may be 
  56. applied.  I am not concerned about adhering religiously to 
  57. his definitions, nor do I wish to confirm or refute his 
  58. conclusions.  My only concern is that you understand the 
  59. discussions in this chapter, and I feel that I could not 
  60. have found a better reference than his for your perusal.
  61.      I am very aware of the hundreds, perhaps even 
  62. thousands, of books which have been jammed on bookshelves in 
  63. recent years simply because a number of people with nothing 
  64. to say realized that money could be had if it was said in a 
  65. book bearing the words Artificial Intelligence.  And if one 
  66. of these books does actually contain useful information, I 
  67. shall probably never know of it because I have vowed not to 
  68. touch a book bearing those words on its front cover.  In 
  69. fact, I would consider myself honored if you would now ink 
  70. over those words in the sentence above and pretend that I 
  71. never wrote them.
  72.      I have recommended Mr. Evans' book because it is not at 
  73. all like those others that are filled with buzz word 
  74. gibberish copied from articles or other books filled with 
  75. identical gibberish.  I have enjoyed the Evans book 
  76. immensely, and I have just finished reading it for the third 
  77. time, so as to have it freshly in mind as I write this 
  78. chapter.  If you disagree with my choice of references, I 
  79. can live with that, but I would be negligent if I did not 
  80. suggest to you the material which has had the greatest 
  81. influence on the material which I present.
  82.  
  83. Onanism Corruptus: The Sin of Self-Modification
  84.   
  85.      At this time, there is a notion that I would like you 
  86. to store someplace in a corner of your mind, and, from time 
  87. to time, as I spend my energy in conveying to you the 
  88. concept and the reality of a software tool that I believe is 
  89. as powerful as the concept and reality of the computer 
  90. itself, I would like you to recall that notion and consider 
  91. the limiting effect that would be placed on software utility 
  92. were it to be universally enforced.  This notion is 
  93. expressed most succinctly on page 92 of 680x0 Programming by 
  94. Example, written by Stan Kelly-Bootle, under the heading 
  95. Logic Behind Rule C.  The precise sentence which I would 
  96. like you to remember, if for no other reason than that it 
  97. alone justifies the existence of this entire chapter, is 
  98. that which follows:
  99.  
  100.    "Motorola discourages self-modifying code, so they 
  101.     make it difficult, but not impossible, for a program 
  102.     to write over itself."
  103.    
  104. I have chosen to use Mr. Kelly-Bootle's remarks, not because 
  105. I consider his to be any more naive than those of other 
  106. authors concerning the same subject.  Rather, I have chosen 
  107. his book to be a very reputable source; to what end would I 
  108. choose a non-reputable source?
  109.      I cannot dispute the sincerity of Mr. Kelly-Bootle's 
  110. remarks, nor can I verify or refute his claim of Motorola's 
  111. concerns and intentions.  But I most certainly can say that 
  112. the notion of a microprocessor manufacturer deliberately 
  113. hindering the processing power of a microprocessor leaves me 
  114. breathless.  OK, that's a little strong.  Actually, the 
  115. vehemency expressed in that sentence is somewhat pretended, 
  116. and is merely a ploy which permits me to ventilate my 
  117. opinion about the notion while indulging in a little private 
  118. sick humor.
  119.      But there is nothing sick about the concept of self-
  120. modifying code, and there is nothing humorous about the idea 
  121. of making it difficult.  Because it is this tool alone which 
  122. permits the intelligence level of software to rise above 
  123. mediocrity.  And say what you will about the power of the 
  124. human brain, in some areas in is overwhelmingly bested by 
  125. even mediocre software; and without the ability to self-
  126. modify its programs, the human brain would be about as 
  127. intelligent as a computer program with the same limitation.
  128.      Unlike the sin of self-gratification, the sin of self-
  129. modification will not cause blindness; however, it can lead 
  130. to coitus interruptus.  This condition becomes evident when 
  131. a row of bombs appear across the video screen.  It means, of 
  132. course, that your self-modifying program has screwed things 
  133. up enough to cause the generation of a software interrupt.
  134.      I think that it is safe for me to say that the more 
  135. intelligence you insert into your algorithms, the more 
  136. likely they are to acquire the attribute of 
  137. unpredictability.  So, if you permit them to engage in the 
  138. perverse activity of self-modification, you had better be 
  139. prepared to protect yourself from the consequences if they 
  140. decide to run amuck.  Of course, your first defensive action 
  141. involves quality control.  You can maintain rigid control by 
  142. thoroughly understanding  each instruction used in an 
  143. adaptive algorithm and by being able to precisely predict 
  144. the effects upon the entire computer system as each is 
  145. executed.
  146.  
  147. Scope of Chapter 7 and Relevant Considerations
  148.   
  149.      The algorithm that is the focus of this chapter is a 
  150. custom trap that reconstructs itself in a disciplined manner 
  151. to form an execution loop about an algorithm under test 
  152. (AUT).  The address of the AUT is passed to the custom trap 
  153. by an invoking program.  The trap copies the AUT to a area 
  154. of memory that is reserved within the boundaries of the 
  155. trap, constructs the execution loop, implements the loop and 
  156. generates appropriate performance data concerning the AUT.  
  157. According to the definition previous established, the 
  158. algorithm to be developed in this chapter is an adaptive 
  159. algorithm.
  160.      As far as I know, there are two ways in which an 
  161. adaptive algorithm can modify itself: it can generate 
  162. executable code within its execution space or it can copy 
  163. executable code from a designated location into that space.  
  164. Of course, there are no restrictions concerning combinations 
  165. of the two methods of adaptation.  In this discussion, I do 
  166. not consider the simple alteration of declared variables to 
  167. be adaptive, although I can understand why some would label 
  168. this as self-modifying.  Neither do I consider the 
  169. alteration of an algorithm's code by an outside agent to be 
  170. adaptive.  When I say that an algorithm is adaptive, I mean 
  171. that its structure permits it to modify its structure.
  172.      While explaining the design and operation of the 
  173. adaptive algorithm, I will mention all of the considerations 
  174. that apply to the programming environment that I have 
  175. adopted; that is the AssemPro environment.  These may not 
  176. apply when other environments are used.  Furthermore, it 
  177. should be understood that I will mention the considerations 
  178. of which I am aware; I can't promise to be infallible.
  179.      As you know, AssemPro provides more than one assembly 
  180. option.  I have shown you some of the effects on produced 
  181. code by each.  As you shall see, the mode used to assemble 
  182. the adaptive algorithm partly determines its structure.  In 
  183. addition, there is the mode of assembly used to generate the 
  184. AUT's code to consider.  The results generated by the 
  185. adaptive algorithm are determined to some extent by the 
  186. assembly mode used on both the adaptive algorithm and the 
  187. algorithm under test.
  188.  
  189. Initial Structure of the Adaptive Algorithm
  190.   
  191.      Figure 7.1A is a representation of the structure of the 
  192. adaptive algorithm as it exists in memory before it has ever 
  193. been invoked.  The structure is defined by four distinct 
  194. sections: an initialization section; a fixed section which 
  195. installs the AUT, replicates the fourth section and 
  196. initiates execution of the loop; a block of memory in which 
  197. the AUT and the replicated fourth section are to reside; and 
  198. the section which contains the loop branch instruction, code 
  199. to generate the performance report and a data section.
  200.   
  201. Figure 7.1A. Structure of the adaptive algorithm prior to 
  202. initial invocation.
  203.  
  204.  
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214.  
  215.  
  216.  
  217.  
  218.  
  219.  
  220.  
  221.  
  222.  
  223.  
  224.  
  225.  
  226.  
  227.      Figure 7.1B illustrates the structure of the program 
  228. that contains the algorithm to be tested.  The hands in this 
  229. figure, and those in figure 7.1C, are there to represent the 
  230. movement of the algorithm under test from the invoking 
  231. program to the adaptive algorithm.  These pictorials are 
  232. actually perverse demonstrations of what does not happen.  I 
  233. wish to graphically impress you with the fact that something 
  234. much more powerful than mere movement of data is involved in 
  235. this and in similar data transactions.  The code which forms 
  236. the algorithm under test is not moved; it is copied.  I feel 
  237. that the implications of this fact is deluded by the 
  238. instruction used to perform the transaction.  The situation 
  239. would be expressed much more clearly if the mnemonic for the 
  240. instruction were copy instead of move.  Nevertheless, I too 
  241. use the word move when I mean copy because that is the 
  242. terminology I was taught.  As long as one remembers that 
  243. this transaction we call move is non-destructive, and that 
  244. the copied data remains intact and can be cloned as often as 
  245. desired, either word can be used to indicated the 
  246. transaction which actually takes place.
  247.  
  248. Figure 7.1B. Structure of the adaptive algorithm invoking 
  249. program.
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272.  
  273.      The thoughts concerning the copying of data, versus the 
  274. movement of data, expressed about figure 7.1B also apply to 
  275. figure 7.1C.  There you see the AUT being moved into the 
  276. space reserved within the adaptive algorithm.  The section 
  277. of reserved space under the block pictorial of the AUT 
  278. implies that the AUT is small enough so that it never fills 
  279. the reserved space.  Of course, the length of the reserved 
  280. space is programmable within the adaptive algorithm, and, in 
  281. fact, the length of the reserved space could be set 
  282. dynamically at run-time.
  283.   
  284. Figure 7.1C. Algorithm under test being installed within the 
  285. reserved space of the adaptive algorithm.
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292.  
  293.  
  294.  
  295.  
  296.  
  297.  
  298.  
  299.  
  300.  
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.      After the AUT has been copied into the reserved space, 
  314. the remaining instructions which form the adaptive algorithm 
  315. and its data must be moved up into the reserved space, 
  316. adjacent to the AUT.  The reason for this will be clearer 
  317. when you view the source and the disassembly listing, but, 
  318. briefly, this is done so that the loop branching instruction 
  319. and attendant data is placed appropriately within the newly 
  320. defined adaptive algorithm structure.  Figure 7.1D 
  321. illustrates the appearance of a portion of the new 
  322. structure.  An important section has been omitted from this 
  323. drawing.
  324.   
  325. Figure 7.1D. Closing the gap between the algorithm under 
  326. test and the fourth section to form the executable loop and 
  327. attendant code.
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.  
  339.  
  340.  
  341.  
  342.  
  343.  
  344.  
  345.  
  346.  
  347.  
  348.  
  349.  
  350.  
  351.  
  352.  
  353.  
  354.  
  355.  
  356.      Figure 7.1E is a pictorial of the adaptive algorithm 
  357. structure after its initial invocation.  There you see the 
  358. section that was omitted from figure 7.1D.  Remember that 
  359. the Movable Loop Section and Data Section is not moved; it 
  360. is copied; therefore, the original section of code remains 
  361. in place, until it is removed deliberately or until the 
  362. adaptive algorithm is removed from memory.  There is no 
  363. reason that instructions to remove that section could not be 
  364. included in the adaptive algorithm.  I did not include such 
  365. instructions in this algorithm because the movable sections 
  366. are replicated during each invocation of the trap; 
  367. therefore, they must remain intact.  The structure shown in 
  368. figure 7.1E is valid for all future invocations of the 
  369. adaptive algorithm.  The initially installed AUT and 
  370. attendant code is simply overwritten by future invocations.
  371.  
  372. Figure 7.1E. Structure of the adaptive algorithm after the 
  373. initial invocation and during all subsequent invocations.
  374.  
  375.  
  376.  
  377.  
  378.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.      I have designed the adaptive algorithm as a custom trap 
  397. so that it need simply be invoked by a program containing an 
  398. algorithm for which the execution speed and requisite memory 
  399. is desired.  When I began to design this trap, I realized 
  400. that I could not anticipate all possible ramifications of 
  401. AUT's assembled in the various assembly modes that I have 
  402. discussed, nor could I apriorily judge the most suitable 
  403. mode of assembly for the adaptive algorithm.  Therefore, I 
  404. prepared two programs: one designed for PC-relative 
  405. assembly, the other for Relocatable assembly.  Program 34 is 
  406. a listing of the adaptive algorithm designed for PC-relative 
  407. assembly.  The program installs the adaptive algorithm as 
  408. custom trap #9.  A routine with the same trap number was 
  409. used during the development of the SPEEDTST utility, but its 
  410. usefulness in that function has expired, so it would be best 
  411. not to have the older trap #9 routine in a position that 
  412. might cause confusion about which routine is installed.
  413.  
  414. Program 34. The adaptive algorithm designed as a custom 
  415. trap.  This particular program has been designed for 
  416. assembly in the PC-relative mode.
  417.  
  418.  ; Program Name: TRAP_9P.S
  419.  ; Version 1.009
  420.  
  421.  ; Assembly Instructions:
  422.  
  423.  ;    Assemble in PC-relative mode and save with a PRG extension.  TRAP_9R.S
  424.  ; is a version of this program that must be assembled in Relocatable mode.
  425.  ; I have prepared two versions because I can't predict the precise requirements
  426.  ; of all possible algorithms which might invoke the custom trap that is 
  427.  ; installed by this program.
  428.  
  429.  ; Program Function:
  430.  
  431.  ;    This is a LSR program that establishes a user defined trap #9.  It may
  432.  ; be executed from the desktop, but you may prefer to copy it to the AUTO
  433.  ; folder of your boot partition or floppy disk so that it will execute
  434.  ; automatically during boot.
  435.  
  436. program_start:                  ; Calculate program size and retain result.
  437.  lea        program_end, a3     ; Fetch program end address.
  438.  suba.l     4(a7), a3           ; Subtract basepage address.
  439.  
  440. enter_supervisor_mode:
  441.  move.l     #0, -(sp)           ; The zero turns on supervisor mode.
  442.  move.w     #$20, -(sp)         ; Function = super = GEMDOS $20.
  443.  trap       #1                  ; Supervisor stack pointer (SSP) returned in D0.
  444.  addq.l     #6, sp             
  445.  movea.l    d0, a5              ; Save SSP in scratch register.
  446.  
  447. install_trap_9_routine:         ; Note: pointer = vector = pointer.
  448.  lea        trap_9_routine, a0  ; Fetch address of trap #9 routine.
  449.  move.l     a0, $A4             ; Store trap address at pointer address.
  450.  
  451. enter_user_mode:
  452.  pea        (a5)                ; Restore supervisor stack pointer.
  453.  move.w     #$20, -(sp)         ; Function = super = GEMDOS $20.
  454.  trap       #1
  455.  addq.l     #6, sp 
  456.  
  457. relinquish_processor_control:   ; Maintain memory residency.
  458.  move.w    #0, -(sp)            ; Exit code. 
  459.  move.l    a3, -(sp)            ; Program size.
  460.  move.w    #$31, -(sp)          ; Function = ptermres = GEMDOS $31.
  461.  trap      #1
  462.  
  463. trap_9_routine:
  464.  
  465.  ; NOTE: You may want to execute a program that invokes this trap from the
  466.  ;       AssemPro debugger and single step through the trap instructions, or
  467.  ;       you many want to set breakpoints and use the "Run program" button to
  468.  ;       execute to a breakpoint.  It the exercise of this latter option that
  469.  ;       can cause problems.  If you want to set a breakpoint at an instruction
  470.  ;       that occurs before the "reserved space", no precautions need be taken,
  471.  ;       except that you must realize that you could halt at a position after
  472.  ;       the start time has been initialized, and the execution time will be
  473.  ;       accumulating during the halt.
  474.  
  475.  ;       But, if you want to set a breakpoint at at an instruction that occurs
  476.  ;       after the "reserved space", you should not do so until the instructions
  477.  ;       that perform the bulk move have been executed.  If you set a breakpoint
  478.  ;       at an instruction in the program space which follows the "reserved
  479.  ;       space" and then execute the bulk move instructions, the breakpoint you
  480.  ;       have set will cause an illegal command error. 
  481.  
  482.  ; This custom trap must be invoked by a program which contains one or more
  483.  ; algorithms for which performance data, in the form of execution time and
  484.  ; requisite memory, is desired.  The trap must be invoked once for each 
  485.  ; algorithm under test (AUT).  The trap is intended to be a performance 
  486.  ; report generator so that performance data for specific algorithms can be
  487.  ; compared.
  488.  
  489.  ; If the program invoking the trap is spawned by SPAWN.TTP, the performance
  490.  ; data will be printed to a file that is created by SPAWN.TTP.  The name of
  491.  ; the file will be the name of the spawned program with a DAT suffix.
  492.  
  493.  ; If the program invoking the trap is executed from the desktop, the 
  494.  ; performance data will be printed to the screen.
  495.  
  496.  ; The AUT can be assembled in PC-relative or Relocatable mode.
  497.  
  498.  ; The custom trap expects the following parameters to be contained in the
  499.  ; specified registers prior to invocation:
  500.  
  501.  ; A0 = The address of a null terminated header to precede the reported
  502.  ;      AUT execution time.
  503.  
  504.  ; A1 = The address of a null terminated header to precede the reported
  505.  ;      AUT requisite memory.
  506.  
  507.  ; A3 = The starting address of an algorithm containing one or more instructions.
  508.  ;      This algorithm becomes the AUT upon invocation of the trap.
  509.  
  510.  ; A4 = The ending address of the AUT.
  511.  
  512.  ; A5 = At the initial invocation by a specific program, A5 is expected to
  513.  ;      contain the address of a null terminated heading that is a brief
  514.  ;      description of the data that is to be reported by the trap.  During
  515.  ;      all subsequent invocations by that program, A5 must contain the
  516.  ;      address of a null string.
  517.  
  518.  ; D7 = A word length decimal value which specifies the number of times the
  519.  ;      the AUT is to be executed in a loop in order to generate the execution
  520.  ;      time data.  Register D7 is the only register which cannot be used by
  521.  ;      the AUT.  That's because D7 is used as the AUT execution loop counter.
  522.  
  523.  ; The custom trap uses the information passed in A3, A4 and D7 to construct
  524.  ; a loop around the AUT.  The loop is executed the number of times specified
  525.  ; in register D7.  The time required to execute the loop is calculated and
  526.  ; printed along with the AUT's requisite memory.
  527.  
  528.  ; How Trap #9 Works:
  529.  
  530.  ;     The custom trap is an intelligent, self-modifying algorithm.  Prior
  531.  ; to an initial invocation, the trap #9 routine is composed of three sections.
  532.  ; The first section contains instructions which are permanently located.  The
  533.  ; second section is a 1,024 byte block of reserved space into which the AUT
  534.  ; and the third section is to be copied.  The third section contains the custom
  535.  ; trap instructions that must be copied so that the first instruction in the
  536.  ; third section immediately follows the last instruction of the algorithm
  537.  ; under test.  The size that I chose for the reserved space was arbitrary.
  538.    
  539.  ;     After an invocation, the custom trap calculates the number of bytes in
  540.  ; the algorithm under test.  Then it initializes register D7 for the AUT's
  541.  ; execution loop.  After saving the addresses of the headers that were passed
  542.  ; as parameters so that the registers in which they were passed can be used
  543.  ; by trap #9 and/or the algorithm under test, the trap prints the AUT's
  544.  ; primary heading and the execution time header.  Then it copies the AUT into
  545.  ; the reserved space.
  546.  
  547.  ;     After the AUT has been copied into the reserved space, the instructions
  548.  ; and data in the third section of the custom trap are moved into immediate
  549.  ; proximity of the AUT so that the first instruction of section three follows
  550.  ; immediately after the last instruction of the algorithm under test.
  551.  
  552.  ;     The AUT is executed the number of times requested via the value passed
  553.  ; in D7, then the execution time and requisite memory of the AUT are printed.
  554.  
  555.  ;     After the custom trap has been invoked once, the reserved space will
  556.  ; not be completely clear during the remaining portion of the power-up cycle.
  557.  ; When the trap is subsequently invoked, the instructions that are already in
  558.  ; the reserved space will simply be overwritten by the instructions of the
  559.  ; new algorithm under test and those of the third section.
  560.  
  561. calculate_length_of_AUT:
  562.  suba.l     a3, a4               ; Subtract start address from end address.
  563.  
  564. save_heading_addresses:
  565.  lea        time_header, a2      ; Header to precede reported execution time.
  566.  move.l     a0, (a2)            
  567.  lea        memory_header, a2    ; Header to precede reported requisite memory.
  568.  move.l     a1, (a2)           
  569.  
  570. transfer_stack_pointer:
  571.  
  572.  ; Upon entrance into this custom trap, A7 contains the address of the system
  573.  ; stack pointer.  Because the system stack may be too short for use by the AUT,
  574.  ; the invoking program must provide a user stack, and, here, I am going to
  575.  ; store the address of that stack in A7.  Before returning to the invoking
  576.  ; program, the system stack pointer must be restored so that the return address
  577.  ; can be found by the processor.
  578.  
  579.  lea        _SSP, a0             ; Fetch address of declared variable.
  580.  move.l     a7, (a0)             ; Save system stack pointer.
  581.  move       USP, a7              ; Transfer to invoking program's stack.
  582.  
  583. print_heading:
  584.  
  585.  ; NOTE: When two or more algorithms are to invoke the trap from a program,
  586.  ;       the heading should be printed only once, at the beginning of the
  587.  ;       report; therefore, the string address in A5 should point to a
  588.  ;       null terminated string during the first invocation of the trap, but
  589.  ;       it should point to a null string on subsequent invocations from the
  590.  ;       same program.
  591.  
  592.  ;       For that reason, the test for NULL string is included below, so that
  593.  ;       only one attempt to print the heading will be made.
  594.  
  595.  tst.b      (a5)                 ; NULL string test.
  596.  beq.s      print_time_header    ; Branch if null.
  597.  movea.l    a5, a0               ; Print heading.
  598.  bsr        print_string
  599.  
  600. print_time_header:
  601.  movea.l    time_header, a0      ; Fetch address of time header.
  602.  bsr        print_string
  603.  
  604. build_algorithm:
  605.  lea        reserved_space, a6   ; Fetch address of reserved space.
  606.  move.w     a4, d3               ; AUT length initializes counter for copy.
  607.  lea        memory, a0           ; Store AUT's requisite memory.
  608.  move.w     d3, (a0)             ; AUT length stored for report.
  609.  subq.w     #1, d3               ; Initialize counter for loop execution.
  610. move_loop:                       ; Move AUT, byte by byte, to the area
  611.  move.b     (a3)+, (a6)+         ; declared as "reserved_space".
  612.  dbra       d3, move_loop        ; Branch until D3 = -1.
  613.  
  614.  ; A6 is now pointing to the location at which the AUT execution loop's DBRA
  615.  ; instruction must be copied.  The DBRA copy must be processed apart from the
  616.  ; other instructions in the custom trap which must be copied to "close up" the
  617.  ; gap between the last statement of the algorithm under test and the rest
  618.  ; of the custom trap's instructions.
  619.  
  620.  lea        algorithm_end, a0    ; Calculate number of bytes in this program
  621.  lea        program_end, a1      ; which must be copied into "reserved_space",
  622.  suba.l     a0, a1               ; then initialize counter D3 with the number
  623.  move.w     a1, d3               ; of bytes to copy.
  624.  subq.w     #4, d3               ; Subtract the DBRA requisite memory.
  625.  movea.l    a0, a1               ; Calculate amount the DBRA instruction must
  626.  suba.l     a6, a1               ; be moved and save the new location in scratch
  627.  movea.l    a6, a5               ; register for displacement correction.
  628.  move.w     2(a0), d0            ; Fetch current DBRA displacement value.
  629.  move.l     (a0)+, (a6)+         ; Move the DBRA instruction.
  630.  add.w      a1, d0               ; Correct DBRA displacement to the value it
  631.  move.w     d0, 2(a5)            ; should be after the move.
  632.  subq.w     #1, d3               ; Initialize counter for bulk copy.
  633. _move_loop:                      ; Move rest of algorithm in a bulk copy.
  634.  move.b     (a0)+, (a6)+
  635.  dbra       d3, _move_loop
  636.  subq.w     #1, d7               ; Initialize D7 for AUT loop execution.
  637.  lea        start_time, a0       ; Fetch address of declared variable.
  638.  suba.l     a1, a0               ; Correct address to after-move location.
  639.  
  640.  ; NOTE: Since processor is in supervisor mode, there is no reason to use
  641.  ;       trap #3 to fetch time.  The 200hz vector can be referenced directly.
  642.  
  643.  move.l     $4BA, (a0)           ; Fetch and store start time.
  644.  
  645. algorithm_start:                 ; new location.
  646. reserved_space:  ds.b  1024      ; Space for loop construction = 1024 bytes.
  647. algorithm_end:
  648.  dbra       d7, algorithm_start
  649.  move.l     $4BA, d0             ; Fetch end time.
  650.  sub.l      start_time, d0       ; Subtract start time from end time.
  651.  trap       #10                  ; Convert to decimal milliseconds and print.
  652. print_memory_header:
  653.  movea.l    memory_header, a0    ; Fetch address of memory header.
  654.  bsr.s      print_string
  655. print_requisite_memory:
  656.  move.w     memory, d1           ; Fetch AUT's requisite memory.
  657.  trap       #4                   ; Returns address of decimal string in A0.
  658.  bsr.s      print_string
  659.  lea        header_1, a0         ; Print requisite memory units label.
  660.  bsr.s      print_string
  661.  
  662.  ; NOTE:  I had thought that I might have to restore the user stack pointer
  663.  ;        before returning to the calling program because I can't know to what
  664.  ;        extent the AUT has corrupted the user stack.
  665.  
  666.  ;        But, as it turns out, since the value in USP is stored in register
  667.  ;        A7 at the beginning of the program, and since the system stack pointer
  668.  ;        is then active and remains so for the duration of the trap invocation,
  669.  ;        only the value in register A7 (which is the system stack pointer, but
  670.  ;        which points to the user stack) is altered; the value in USP remains
  671.  ;        uncorrupted, therefore, nothing needs be restored but the system stack
  672.  ;        pointer (so that it again points to the system stack).
  673.  
  674.  ;        On subsequent invocations the value in USP, which remains stable, will
  675.  ;        simply be restored in A7, as often as the trap is invoked.
  676.  
  677.  movea.l    _SSP, a7             ; Restore system stack pointer so that it
  678.  rte                             ; points to the system stack.
  679.  
  680.  ;
  681.  ; SUBROUTINES
  682.  ;
  683.  
  684. print_string:         
  685.  pea        (a0)
  686.  move.w     #9, -(sp) 
  687.  trap       #1        
  688.  addq.l     #6, sp    
  689.  rts
  690.  
  691.  data
  692. header_1:      dc.b '  bytes',$D,$A,0
  693.  bss
  694.  align
  695. _SSP:          ds.l    1   ; Address of the system stack will be stored here.
  696. start_time:    ds.l    1   ; Variable for time at start of AUT processing.
  697. memory:        ds.w    1   ; Variable for AUT's requisite memory.
  698. time_header:   ds.l    1   ; Points to address of header which is to precede
  699.                            ; the reported AUT processing time.
  700. memory_header: ds.l    1   ; Points to address of header which is to precede
  701.                            ; the reported AUT requisite memory.
  702. program_end:   ds.l    0
  703.  end
  704.  
  705.  
  706.      Comprehension of program 34 will be facilitated with 
  707. reference to a disassembly listing of the program as it 
  708. resides in memory.  Figure 7.2 is a portion of that listing.  
  709. A section of the reserved space has been deleted in order to 
  710. reduce the size of the listing.  This listing shows the code 
  711. for the trap before any program has invoked it.
  712.  
  713. Figure 7.2. Disassembly listing of TRAP_9P.PRG as it resides 
  714. in memory before an initial invocation.
  715.  
  716.  TRAP_9P.PRG Before First Invocation
  717.  
  718. 01FA36 99CB             SUBA.L A3,A4
  719. 01FA38 45FA04B4         LEA $1FEEE(PC),A2
  720. 01FA3C 2488             MOVE.L A0,(A2)
  721. 01FA3E 45FA04B2         LEA $1FEF2(PC),A2
  722. 01FA42 2489             MOVE.L A1,(A2)
  723. 01FA44 41FA049E         LEA $1FEE4(PC),A0
  724. 01FA48 208F             MOVE.L A7,(A0)
  725. 01FA4A 4E6F             MOVE.L USP,A7
  726. 01FA4C 4A15             TST.B (A5)
  727. 01FA4E 6706             BEQ.S $1FA56
  728. 01FA50 204D             MOVEA.L A5,A0
  729. 01FA52 6100047A         BSR $1FECE
  730. 01FA56 207A0496         MOVEA.L $1FEEE(PC),A0
  731. 01FA5A 61000472         BSR $1FECE
  732. 01FA5E 4DFA0046         LEA $1FAA6(PC),A6
  733. 01FA62 360C             MOVE.W A4,D3
  734. 01FA64 41FA0486         LEA $1FEEC(PC),A0
  735. 01FA68 3083             MOVE.W D3,(A0)
  736. 01FA6A 5343             SUBQ.W #1,D3
  737. 01FA6C 1CDB             MOVE.B (A3)+,(A6)+
  738. 01FA6E 51CBFFFC         DBRA D3,$1FA6C
  739. 01FA72 41FA0432         LEA $1FEA6(PC),A0
  740. 01FA76 43FA047E         LEA $1FEF6(PC),A1
  741. 01FA7A 93C8             SUBA.L A0,A1
  742. 01FA7C 3609             MOVE.W A1,D3
  743. 01FA7E 5943             SUBQ.W #4,D3
  744. 01FA80 2248             MOVEA.L A0,A1
  745. 01FA82 93CE             SUBA.L A6,A1
  746. 01FA84 2A4E             MOVEA.L A6,A5
  747. 01FA86 30280002         MOVE.W 2(A0),D0
  748. 01FA8A 2CD8             MOVE.L (A0)+,(A6)+
  749. 01FA8C D049             ADD.W A1,D0
  750. 01FA8E 3B400002         MOVE.W D0,2(A5)
  751. 01FA92 5343             SUBQ.W #1,D3
  752. 01FA94 1CD8             MOVE.B (A0)+,(A6)+
  753. 01FA96 51CBFFFC         DBRA D3,$1FA94
  754. 01FA9A 5347             SUBQ.W #1,D7
  755. 01FA9C 41FA044A         LEA $1FEE8(PC),A0
  756. 01FAA0 91C9             SUBA.L A1,A0
  757. 01FAA2 20B804BA         MOVE.L $4BA,(A0)
  758. 01FAA6 00000000         ORI.B #0,D0
  759. 01FAAA 00000000         ORI.B #0,D0
  760.  
  761.  NOTE: Section of reserved space omitted
  762.        to reduce size of listing.
  763.  
  764. 01FE9E 00000000         ORI.B #0,D0
  765. 01FEA2 00000000         ORI.B #0,D0
  766. 01FEA6 51CFFBFE         DBRA D7,$1FAA6
  767. 01FEAA 203804BA         MOVE.L $4BA,D0
  768. 01FEAE 90BA0038         SUB.L $1FEE8(PC),D0
  769. 01FEB2 4E4A             TRAP #$A
  770. 01FEB4 207A003C         MOVEA.L $1FEF2(PC),A0
  771. 01FEB8 6114             BSR.S $1FECE
  772. 01FEBA 323A0030         MOVE.W $1FEEC(PC),D1
  773. 01FEBE 4E44             TRAP #4
  774. 01FEC0 610C             BSR.S $1FECE
  775. 01FEC2 41FA0016         LEA $1FEDA(PC),A0
  776. 01FEC6 6106             BSR.S $1FECE
  777. 01FEC8 2E7A001A         MOVEA.L $1FEE4(PC),A7
  778. 01FECC 4E73             RTE
  779. 01FECE 4850             PEA (A0)
  780. 01FED0 3F3C0009         MOVE.W #9,-(A7)
  781. 01FED4 4E41             TRAP #1
  782. 01FED6 5C8F             ADDQ.L #6,A7
  783. 01FED8 4E75             RTS
  784. 01FEDA 2020             MOVE.L -(A0),D0
  785. 01FEDC 6279             BHI.S $1FF57
  786. 01FEDE 7465             MOVEQ #$65,D2
  787. 01FEE0 730D             DC.W $730D
  788. 01FEE2 0A00FF0A         EORI.B #$A,D0
  789. 01FEE6 00000000         ORI.B #0,D0
  790. 01FEEA 00000000         ORI.B #0,D0
  791. 01FEEE 00000000         ORI.B #0,D0
  792. 01FEF2 00000000         ORI.B #0,D0
  793.  
  794.  
  795. Analysis of TRAP_9P
  796.   
  797.      The analysis of program 34 begins at the label 
  798. algorithm_start in the source listing, at address 01FAA6 in 
  799. the disassembly listing.  The label reserved_space in the 
  800. source listing is superfluous, serving only to indicate that 
  801. the 1024 bytes of defined space is sandwiched between the 
  802. two labels algorithm_start and algorithm_end, which locate 
  803. the boundaries of the algorithm under test after it has been 
  804. installed.  Note that neither the data nor the bss assembler 
  805. pseudo-ops are used before the ds.b 1024 pseudo-op.  If the 
  806. data and bss pseudo-ops are used in conjunction with the 
  807. ds.b pseudo-op to define the reserved space, AssemPro will 
  808. locate the 1024 bytes of defined space in the program's data 
  809. section; therefore, the space reserved would not be between 
  810. the labels that mark the boundaries of the AUT.  That 
  811. relocation of the reserved space is not necessarily 
  812. prejudicial to the structure of an adaptive algorithm if it 
  813. is considered during the design of the algorithm; but it is 
  814. important to know the precise effect of every instruction 
  815. and pseudo-op when dealing with self-modifying algorithms.
  816.  
  817. Moving the DBRA Instruction
  818.   
  819.      Refer to the dbra instruction at address 01FEA6 in the 
  820. disassembly listing.  The disassembler displays the entire 
  821. instruction in a format that is pleasing to the eye, DBRA 
  822. D7, $1FAA6, because it enables us to readily discern the 
  823. value that will be loaded into the program counter when the 
  824. branch is taken.  But this convenience tends to obscure the 
  825. fact that the instruction exists in memory as 51CFFBFE, 
  826. which is not as pretty, but which more accurately portrays 
  827. the activity involved in assembling and executing the dbra 
  828. instruction.  To wit: the assembler calculates a signed 
  829. displacement between the dbra instruction and a label and 
  830. stores this displacement in the extension word which follows 
  831. the instruction word.  In this particular case, the 
  832. displacement is $FBFE = -1026 (decimal).
  833.      The important thing to realize is that the displacement 
  834. is fixed during assembly and will not change when the dbra 
  835. instruction is copied into the reserved space, following the 
  836. insertion of the AUT.  But the distance between address 
  837. 01FAA6 and the dbra instruction will be less then than it is 
  838. now; therefore, something must be done to alter the value in 
  839. the dbra extension word after the instruction has been 
  840. copied into the reserved space.
  841.      Within the source listing, following the two 
  842. instructions after the move_loop label, there is a note 
  843. concerning the movement of the dbra instruction into the 
  844. reserved space.  It is the necessity for the displacement 
  845. correction which requires that the dbra move be accomplished 
  846. in a single transaction, apart from the movement of the 
  847. other code comprising the movable sections.  The source 
  848. listing documentation which accompanies the instructions 
  849. following the note explains the steps involved in 
  850. calculating a new displacement value, but since some of 
  851. those instructions are specific to the movement of the code 
  852. following the dbra instruction, I will repeat the steps here 
  853. so that cognition may be confirmed.
  854.  
  855.      1. Calculate the total number of bytes of code which 
  856.         must be copied into the reserved space after the AUT 
  857.         has been installed.  This value is the number of 
  858.         bytes existing between the label algorithm_end and 
  859.         the end of the program. It is calculated in register 
  860.         A1, then copied into register D3, which is used as a 
  861.         loop counter when all but the dbra instruction 
  862.         portion of the movable sections are copied into the 
  863.         reserved space.
  864.  
  865.      2. Because the dbra instruction will be moved apart 
  866.         from the other instruction in the section, its 
  867.         requisite memory (4 bytes) must be subtracted from 
  868.         the counter, D3, before the bulk copy takes place.
  869.  
  870.      3. Calculate the displacement between the dbra 
  871.         instruction's current location and the location at 
  872.         which it is to be copied.  The dbra instruction's 
  873.         current location is marked by the label 
  874.         algorithm_end, which is still stored in register A0.  
  875.         The value in A0 must be preserved for future 
  876.         calculations, therefore, it is copied into A1.  The 
  877.         value in register A6 is the location to which the 
  878.         dbra instruction must be moved.  Subtracting A6 from 
  879.         A1 puts the number of bytes that the dbra 
  880.         instruction must be moved into A1.  The extension 
  881.         word correction to follow requires that the value in 
  882.         A6 be preserved, so it is copied into register A5.
  883.  
  884.      4. Fetch the current dbra displacement value.  In the 
  885.         source listing, you can see that this value is 
  886.         stored in register D0.
  887.  
  888.      5. Move (or copy) the dbra instruction into its new 
  889.         location.
  890.  
  891.      6. Correct the dbra instruction's displacement value.  
  892.         The correction must be a positive value because the 
  893.         distance between the branch instruction and the 
  894.         branch location has decreased.  Register A1 contains 
  895.         the previously calculated correction, which is 
  896.         simply the number of bytes that the dbra instruction 
  897.         was moved.  In the source listing, you can see that 
  898.         the positive value in A1 is added to the negative 
  899.         value in D0 to obtain the new displacement value.  
  900.         Then the contents of D0 are written to the dbra 
  901.         extension word's new location at 2(A5) with a self-
  902.         modifying instruction.
  903.  
  904.      The effect of the above steps can be seen in figure 
  905. 7.3, a disassembly listing of program 34 after a single 
  906. instruction AUT, MULU #5,D0, has been installed in the 
  907. reserved space, at address 01FAA6.  The new dbra 
  908. displacement is shown in the instruction following; it is 
  909. $FFFA = -6 (decimal).  Within the listing are several notes, 
  910. shown in boldface, that explain specific instruction groups.
  911.  
  912. Figure 7.3 Disassembly listing of the adaptive algorithm 
  913. portion of TRAP_9P.PRG as it resides in memory after the 
  914. initial invocation.
  915.  
  916.  TRAP_9P.PRG After First Invocation
  917.  
  918. 01FA36 99CB         SUBA.L A3,A4
  919. 01FA38 45FA04B4     LEA $1FEEE(PC),A2
  920. 01FA3C 2488         MOVE.L A0,(A2)
  921. 01FA3E 45FA04B2     LEA $1FEF2(PC),A2
  922. 01FA42 2489         MOVE.L A1,(A2)
  923. 01FA44 41FA049E     LEA $1FEE4(PC),A0
  924. 01FA48 208F         MOVE.L A7,(A0)
  925. 01FA4A 4E6F         MOVE.L USP,A7
  926. 01FA4C 4A15         TST.B (A5)
  927. 01FA4E 6706         BEQ.S $1FA56
  928. 01FA50 204D         MOVEA.L A5,A0
  929. 01FA52 6100047A     BSR $1FECE
  930. 01FA56 207A0496     MOVEA.L $1FEEE(PC),A0
  931. 01FA5A 61000472     BSR $1FECE
  932. 01FA5E 4DFA0046     LEA $1FAA6(PC),A6
  933. 01FA62 360C         MOVE.W A4,D3
  934. 01FA64 41FA0486     LEA $1FEEC(PC),A0
  935. 01FA68 3083         MOVE.W D3,(A0)
  936. 01FA6A 5343         SUBQ.W #1,D3
  937. 01FA6C 1CDB         MOVE.B (A3)+,(A6)+
  938. 01FA6E 51CBFFFC     DBRA D3,$1FA6C
  939. 01FA72 41FA0432     LEA $1FEA6(PC),A0
  940. 01FA76 43FA047E     LEA $1FEF6(PC),A1
  941. 01FA7A 93C8         SUBA.L A0,A1
  942. 01FA7C 3609         MOVE.W A1,D3
  943. 01FA7E 5943         SUBQ.W #4,D3
  944. 01FA80 2248         MOVEA.L A0,A1
  945. 01FA82 93CE         SUBA.L A6,A1
  946. 01FA84 2A4E         MOVEA.L A6,A5
  947. 01FA86 30280002     MOVE.W 2(A0),D0
  948. 01FA8A 2CD8         MOVE.L (A0)+,(A6)+
  949. 01FA8C D049         ADD.W A1,D0
  950. 01FA8E 3B400002     MOVE.W D0,2(A5)
  951. 01FA92 5343         SUBQ.W #1,D3
  952. 01FA94 1CD8         MOVE.B (A0)+,(A6)+
  953. 01FA96 51CBFFFC     DBRA D3,$1FA94
  954. 01FA9A 5347         SUBQ.W #1,D7
  955. 01FA9C 41FA044A     LEA $1FEE8(PC),A0
  956. 01FAA0 91C9         SUBA.L A1,A0
  957. 01FAA2 20B804BA     MOVE.L $4BA,(A0)
  958. 01FAA6 C0FC0005     MULU #5,D0      ; AUT
  959. 01FAAA 51CFFFFA     DBRA D7,$1FAA6  ; FFFA = -6
  960. 01FAAE 203804BA     MOVE.L $4BA,D0
  961. 01FAB2 90BA0038     SUB.L $1FAEC(PC),D0
  962. 01FAB6 4E4A         TRAP #$A
  963. 01FAB8 207A003C     MOVEA.L $1FAF6(PC),A0
  964. 01FABC 6114         BSR.S $1FAD2
  965. 01FABE 323A0030     MOVE.W $1FAF0(PC),D1
  966. 01FAC2 4E44         TRAP #4
  967. 01FAC4 610C         BSR.S $1FAD2
  968. 01FAC6 41FA0016     LEA $1FADE(PC),A0
  969. 01FACA 6106         BSR.S $1FAD2
  970. 01FACC 2E7A001A     MOVEA.L $1FAE8(PC),A7
  971. 01FAD0 4E73         RTE
  972.  
  973.  Below is the print_string subroutine.
  974.  
  975. 01FAD2 4850         PEA (A0)
  976. 01FAD4 3F3C0009     MOVE.W #9,-(A7)
  977. 01FAD8 4E41         TRAP #1
  978. 01FADA 5C8F         ADDQ.L #6,A7
  979. 01FADC 4E75         RTS
  980.  
  981.  The data section appears below.
  982.  
  983. 01FADE 2020         MOVE.L -(A0),D0  ;'  '
  984. 01FAE0 6279         BHI.S $1FB5B     ;by
  985. 01FAE2 7465         MOVEQ #$65,D2    ;te
  986. 01FAE4 730D         DC.W $730D       ;s
  987.  
  988.  _SSP => $01FAE8
  989.  
  990. 01FAE6 0A000003     EORI.B #3,D0
  991. 01FAEA EF3A         ROL.B D7,D2
  992.  
  993.  start_time (new address) = 01FAEC
  994.  
  995. 01FAEC 00000000     ORI.B #0,D0
  996.  
  997.  memory => 01FAF0
  998.  time_header => 01FAF2
  999.       
  1000. 01FAF0 00040006     ORI.B #6,D4
  1001.  
  1002.  memory_header => 01FAF6
  1003.  
  1004. 01FAF4 DBB90006DC1F ADD.L D5,$6DC1F
  1005. 01FAFA 00000000     ORI.B #0,D0
  1006. 01FAFE 00000000     ORI.B #0,D0
  1007.  
  1008.  NOTE: Section of reserved space omitted
  1009.        to reduce size of listing.
  1010.  
  1011. 01FE9E 00000000     ORI.B #0,D0
  1012. 01FEA2 00000000     ORI.B #0,D0
  1013.  
  1014.  Below is the original movable block.  It has not
  1015.  been effected by the move.
  1016.  
  1017. 01FEA6 51CFFBFE     DBRA D7,$1FAA6
  1018. 01FEAA 203804BA     MOVE.L $4BA,D0
  1019. 01FEAE 90BA0038     SUB.L $1FEE8(PC),D0
  1020. 01FEB2 4E4A         TRAP #$A
  1021. 01FEB4 207A003C     MOVEA.L $1FEF2(PC),A0
  1022. 01FEB8 6114         BSR.S $1FECE
  1023. 01FEBA 323A0030     MOVE.W $1FEEC(PC),D1
  1024. 01FEBE 4E44         TRAP #4
  1025. 01FEC0 610C         BSR.S $1FECE
  1026. 01FEC2 41FA0016     LEA $1FEDA(PC),A0
  1027. 01FEC6 6106         BSR.S $1FECE
  1028. 01FEC8 2E7A001A     MOVEA.L $1FEE4(PC),A7
  1029. 01FECC 4E73         RTE
  1030. 01FECE 4850         PEA (A0)
  1031. 01FED0 3F3C0009     MOVE.W #9,-(A7)
  1032. 01FED4 4E41         TRAP #1
  1033. 01FED6 5C8F         ADDQ.L #6,A7
  1034. 01FED8 4E75         RTS
  1035. 01FEDA 2020         MOVE.L -(A0),D0
  1036. 01FEDC 6279         BHI.S $1FF57
  1037. 01FEDE 7465         MOVEQ #$65,D2
  1038. 01FEE0 730D         DC.W $730D
  1039. 01FEE2 0A000003     EORI.B #3,D0
  1040. 01FEE6 EF3A         ROL.B D7,D2
  1041.  
  1042.  start_time (old address) = 01FEE8
  1043.  
  1044. 01FEE8 00000000     ORI.B #0,D0
  1045. 01FEEC 00040006     ORI.B #6,D4
  1046. 01FEF0 DBB90006DC1F ADD.L D5,$6DC1F
  1047.  
  1048.           
  1049. The Bulk Move
  1050.   
  1051.      The rest of the code in the movable section can be 
  1052. moved as a block.  This transaction takes place at the 
  1053. _move_loop label in the source listing, at address 01FA94 in 
  1054. the disassembly listings.  Note that immediately after the 
  1055. block move, the address of the declared variable start_time 
  1056. is loaded into register A0, and that, before the time is 
  1057. fetched, the contents of register A1 are subtracted from 
  1058. those of A0 to correct the address in register A0.  These 
  1059. transactions take place at addresses 01FA9C and 01FAA0 of 
  1060. the disassembly listings.
  1061.  
  1062. Why The Address Of start_time Must BE Corrected
  1063.   
  1064.      From time to time, we must remind ourselves that pc-
  1065. relative addressing can be used discriminatingly, by 
  1066. including the (pc) notation in the source operand, or it can 
  1067. be forced by the PC-relative assembly mode.  Now, although 
  1068. it may not be obvious from discussions in the references, 
  1069. when pc-relative addressing is used in the source operand of 
  1070. the LEA instruction, it, like the DBRA instruction, performs 
  1071. its transaction with a displacement stored in its extension 
  1072. word.  This is evident from the machine code at address 
  1073. 01FA9C, where the extension word can be seen to be $044A = 
  1074. 1098 (decimal).  To confirm that this is indeed the 
  1075. displacement between the LEA instruction and the label 
  1076. start_time we need only subtract their addresses:
  1077.  
  1078.                $01FEE8 - $01FA9C = $44C
  1079.   
  1080. and from this subtract the size of the LEA instruction:
  1081.   
  1082.                 $44C - 2 bytes = $44A.
  1083.   
  1084.      Now, to decide whether or not a correction to this 
  1085. displacement is necessary, we need only determine whether or 
  1086. not the displacement between the two addresses is altered by 
  1087. the bulk move.  Well, of course it does.  The instruction 
  1088. and the label will be closer after the move, and, since the 
  1089. label will be moved the same distance as was the dbra 
  1090. instruction, the same correction factor, which is still in 
  1091. A1,  must be applied.  The displacement in the LEA 
  1092. instruction's extension word must be corrected at this point 
  1093. in the program because the location in which the start time 
  1094. is stored will be accessed to compute the AUT's execution 
  1095. time after the algorithm_start loop has been executed.  You 
  1096. can see that transaction taking place at address 01FAB2 of 
  1097. figure 7.3.  There you can also see that the new 
  1098. displacement is $0038, and that start_time's new address is 
  1099. 01FAEC.
  1100.      Program 35 is a source listing of the program designed 
  1101. to confirm the rudimentary reliability of the adaptive 
  1102. algorithm in program 34.  The performance data for the AUTs 
  1103. in program 35 should (and does) match that obtained with 
  1104. program 32 because the algorithms were copied from that 
  1105. program.  The data generated by program 35 follows its 
  1106. listing.
  1107.  
  1108. Program 35. This program is used to verify that program 34 
  1109. functions correctly.
  1110.  
  1111.  ; Program Name: TRAP9TST.S
  1112.  ;      Version: 1.001
  1113.  
  1114.  ; Assembly Instructions:
  1115.  
  1116.  ;     Assemble in PC-relative mode and save with a TOS extension.
  1117.  
  1118.  ; Execution Instructions:
  1119.  
  1120.  ;     Execute from the desktop; or execute SPAWN.TTP, type TRAP9TST.TOS on
  1121.  ; its command line and view this program's output in TRAP9TST.DAT.
  1122.  
  1123.  ; Program Function:
  1124.  
  1125.  ;     Measures the speed of multiplication algorithms.  Verifies that
  1126.  ; TRAP_9P functions correctly.
  1127.  
  1128. calculate_program_size:
  1129.  lea        -$102(pc), a1       ; Fetch basepage start address.
  1130.  lea        program_end, a0     ; Fetch program end = array address.
  1131.  trap       #6                  ; Return unused memory to op system.
  1132.  lea        stack, a7
  1133.  
  1134. the_mulu_instruction:
  1135.  lea        header_1, a0       
  1136.  lea        header_4, a1
  1137.  lea        mulu_algorithm_start, a3
  1138.  lea        mulu_algorithm_end, a4
  1139.  lea        heading, a5
  1140.  move.w     #50000, d7
  1141.  
  1142. invoke_trap_9:
  1143.  trap       #9
  1144.  
  1145. addition:
  1146.  lea        header_2, a0       
  1147.  lea        header_5, a1
  1148.  lea        addition_algorithm_start, a3
  1149.  lea        addition_algorithm_end, a4
  1150.  lea        heading, a5
  1151.  move.b     #0, (a5)            ; Store a NULL in first byte to create a
  1152.  move.w     #50000, d7          ; null string so that heading gets printed
  1153.  trap       #9                  ; only once.
  1154.  
  1155. shift_and_add:
  1156.  lea        header_3, a0       
  1157.  lea        header_6, a1
  1158.  lea        shift_and_add_algorithm_start, a3
  1159.  lea        shift_and_add_algorithm_end, a4
  1160.  lea        heading, a5
  1161.  move.w     #50000, d7
  1162.  trap       #9
  1163.  
  1164. terminate:
  1165.  trap       #8
  1166.  
  1167. mulu_algorithm_start:
  1168.  mulu       #5, d0              ; Instruction in the loop.
  1169. mulu_algorithm_end:
  1170.  
  1171. addition_algorithm_start:
  1172.  move.l     d0, d2              ; To add one.   
  1173.  add.l      d0, d0              ; To double to two.
  1174.  add.l      d0, d0              ; To double to four.
  1175.  add.l      d2, d0              ; To complete multiplication by 5.
  1176. addition_algorithm_end:
  1177.  
  1178. shift_and_add_algorithm_start:
  1179.  move.l     d0, d2              ; Save a copy to add.
  1180.  asl.l      #2, d0              ; Shift to multiply by 4. 
  1181.  add.l      d2, d0              ; To complete multiplication by 5.
  1182. shift_and_add_algorithm_end:
  1183.  
  1184.  data
  1185. heading:      dc.b   "TRAP9TST Execution Results",$D,$A,$D,$A,0
  1186. header_1:     dc.b       "   MULU time:                    ",0
  1187. header_2:     dc.b       "   Addition time:                ",0
  1188. header_3:     dc.b       "   Shift and add time:           ",0
  1189. header_4:     dc.b       "   MULU requisite memory:           ",0
  1190. header_5:     dc.b       "   Addition requisite memory:       ",0
  1191. header_6:     dc.b       "   Shift and add requisite memory:  ",0
  1192.  bss
  1193.  align
  1194.               ds.l 96
  1195. stack:        ds.l  0
  1196. program_end:  ds.l  0
  1197.  end
  1198.  
  1199. TRAP9TST Execution Results
  1200.  
  1201.    MULU time:                      360  milliseconds
  1202.    MULU requisite memory:            4  bytes
  1203.    Addition time:                  260  milliseconds
  1204.    Addition requisite memory:        8  bytes
  1205.    Shift and add time:             235  milliseconds
  1206.    Shift and add requisite memory:   6  bytes
  1207.  
  1208.  
  1209. A Relocatable Version of the Adaptive Algorithm
  1210.  
  1211.      The adaptive algorithm may also be installed as a trap 
  1212. that has been assembled in AssemPro's Relocatable mode.  
  1213. According to definitions previously established, program 36 
  1214. is probably more appropriately designated as a Combo version 
  1215. of program 34, because pc-relative addressing is used as 
  1216. circumstances permit.  The choice of assembly modes for LSR 
  1217. programs is a bit more engaging than it is for other types 
  1218. of programs because the length of time that the program is 
  1219. resident is so much longer than the load time.  It may be 
  1220. that one decides to accept the longer load time as a 
  1221. condition of receiving some other benefit via Relocatable 
  1222. assembly, or it may be that circumstances dictate the 
  1223. assembly mode.
  1224.      From the beginning of the book, my emphasis has been on 
  1225. the quest for speed.  To me it seems that all other 
  1226. desirable software attributes precipitate naturally from the 
  1227. quest for this single feature.  Consider the reason we use 
  1228. computers in the first place.  Were speed not the most 
  1229. compelling issue, computers would probably not have been 
  1230. invented.  That's why, in formulating my thoughts for the 
  1231. current discussion, I anticipated that the relative speed of 
  1232. the PC-relative assembled adaptive algorithm versus that of 
  1233. the Relocatable assembled algorithm would be the most 
  1234. obvious primary topic.  But, as it turns out, my attention 
  1235. was drawn to a more compelling consideration: that of the 
  1236. AUT's addressing and assembly modes.
  1237.      As I mentioned in program 34's documentation, at the 
  1238. time that I designed that program, I could not predict the 
  1239. requirements of all possible AUTs, but I did guess that a 
  1240. Relocatable version of the adaptive algorithm might be 
  1241. desirable, or required, for some invoking algorithms.  
  1242. Simultaneously, I guessed that there would be times when one 
  1243. or the other assembly modes might be preferable for the AUT.  
  1244. It was while I was comparing the first few lines of the 
  1245. disassembly listing for the Relocatable version of the 
  1246. custom trap to that of the PC-relative version that I was 
  1247. struck with the realization that the assembly mode chosen 
  1248. for the AUT would at times be dictated by the instructions 
  1249. comprising that algorithm.  Then, if instructions in the AUT 
  1250. were to store data in locations being referenced via a 
  1251. displacement, that data could be written into the adaptive 
  1252. algorithm's program area, thereby disruptively modifying the 
  1253. adaptive algorithm.  To illustrate this phenomenon, I have 
  1254. chosen a suitable AUT, but first, let me present the source 
  1255. file and disassembly listing for program 36.
  1256.  
  1257. Program 36. The adaptive algorithm designed for Relocatable 
  1258. Assembly.  Execution results follow the listing.
  1259.  
  1260.  ; Program Name: TRAP_9R.S
  1261.  ; Version 1.005
  1262.  
  1263.  ; Assembly Instructions:
  1264.  
  1265.  ;    Assemble in Relocatable mode and save with a PRG extension.  TRAP_9P.S
  1266.  ; is a version of this program that can be assembled in PC-relative mode.
  1267.  ; I have prepared two versions because I can't predict the precise requirements
  1268.  ; of all possible algorithms which might invoke the custom trap that is 
  1269.  ; installed by this program.
  1270.  
  1271.  ; Program Function:
  1272.  
  1273.  ;    This is a LSR program that establishes a user defined trap #9.  It may
  1274.  ; be executed from the desktop, but you may prefer to copy it to the AUTO
  1275.  ; folder of your boot partition or floppy disk so that it will execute
  1276.  ; automatically during boot.
  1277.  
  1278. program_start:                  ; Calculate program size and retain result.
  1279.  lea        program_end(pc), a3 ; Fetch program end address.
  1280.  suba.l     4(a7), a3           ; Subtract basepage address.
  1281.  
  1282. enter_supervisor_mode:
  1283.  move.l     #0, -(sp)           ; The zero turns on supervisor mode.
  1284.  move.w     #$20, -(sp)         ; Function = super = GEMDOS $20.
  1285.  trap       #1                  ; Go to supervisor mode.
  1286.  addq.l     #6, sp              ; Supervisor stack pointer (SSP) returned in D0.
  1287.  movea.l    d0, a5              ; Save SSP in scratch register.
  1288.  
  1289. install_trap_9_routine:         ; Store trap address at pointer address.
  1290.  move.l     #trap_9_routine, $A4
  1291.  
  1292. enter_user_mode:
  1293.  pea        (a5)                ; Restore supervisor stack pointer.
  1294.  move.w     #$20, -(sp)         ; Function = super = GEMDOS $20.
  1295.  trap       #1
  1296.  addq.l     #6, sp
  1297.  
  1298. relinquish_processor_control:   ; Maintain memory residency.
  1299.  move.w    #0, -(sp)            ; Exit code.
  1300.  move.l    a3, -(sp)            ; Program size.
  1301.  move.w    #$31, -(sp)          ; Function = ptermres = GEMDOS $31.
  1302.  trap      #1
  1303.  
  1304. trap_9_routine:
  1305.  
  1306.  ; See documentation in program TRAP_9P.S.
  1307.  
  1308. calculate_length_of_AUT:
  1309.  suba.l     a3, a4               ; Subtract start address from end address.
  1310.  
  1311. save_heading_addresses:
  1312.  move.l     a0, time_header      ; Header to precede reported execution time.
  1313.  move.l     a1, memory_header    ; Header to precede reported requisite memory.
  1314.                              
  1315. transfer_stack_pointer:
  1316.  
  1317.  ; See documentation in program TRAP_9P.S.
  1318.  
  1319.  move.l     a7, _SSP             ; Save system stack pointer.
  1320.  move       USP, a7              ; Transfer to invoking program's stack.
  1321.  
  1322. print_heading:
  1323.  
  1324.  ; See documentation in program TRAP_9P.S.
  1325.  
  1326.  tst.b      (a5)                 ; NULL string test.
  1327.  beq.s      print_time_header    ; Branch if null.
  1328.  movea.l    a5, a0               ; Print heading.
  1329.  bsr        print_string
  1330.  
  1331. print_time_header:
  1332.  movea.l    time_header(pc), a0  ; Fetch address of time header.
  1333.  bsr        print_string
  1334.  
  1335. build_algorithm:
  1336.  lea        reserved(pc), a6     ; Fetch address of reserved space.
  1337.  move.w     a4, d3               ; AUT length initializes counter for copy.
  1338.  move.w     d3, memory           ; AUT length stored for report.
  1339.  subq.w     #1, d3               ; Initialize counter for loop execution.
  1340. move_loop:                       ; Move AUT, byte by byte, to the area
  1341.  move.b     (a3)+, (a6)+         ; declared as "reserved".
  1342.  dbra       d3, move_loop        ; Branch until D3 = -1.
  1343.  
  1344.  ; See documentation in program TRAP_9P.S.
  1345.  
  1346.  lea        aut_end(pc), a0      ; Calculate number of bytes in this program
  1347.  lea        program_end(pc), a1  ; which must be moved into "reserved space",
  1348.  suba.l     a0, a1               ; then initialize counter D3 with the number
  1349.  move.w     a1, d3               ; of bytes to copy.
  1350.  subq.w     #4, d3               ; Subtract the DBRA requisite memory.
  1351.  movea.l    a0, a1               ; Calculate amount the DBRA instruction must
  1352.  suba.l     a6, a1               ; be moved and save the new location in scratch
  1353.  movea.l    a6, a5               ; register for displacement correction.
  1354.  move.w     2(a0), d0            ; Fetch current DBRA displacement value.
  1355.  move.l     (a0)+, (a6)+         ; Move the DBRA instruction.
  1356.  add.w      a1, d0               ; Correct DBRA displacement to the value it
  1357.  move.w     d0, 2(a5)            ; should be after the move.
  1358.  subq.w     #1, d3               ; Initialize counter for bulk copy.
  1359. _move_loop:                      ; Move rest of algorithm in a bulk copy.
  1360.  move.b     (a0)+, (a6)+
  1361.  dbra       d3, _move_loop
  1362.  subq.w     #1, d7               ; Initialize D7 for AUT loop execution.
  1363.  lea        start_time(pc), a0   ; Fetch address of declared variable.
  1364.  
  1365.  ; NOTE: No correction is necessary for the start time variable, as it was
  1366.  ;       in the PC-relative assembled program TRAP_9P, if pc-relative
  1367.  ;       addressing is not used for the label in the instruction below that
  1368.  ;       subtracts the contents of start_time from d0.  That instruction is
  1369.  ;       marked by asterisks below.  In the TRAP_9P program AssemPro used
  1370.  ;       pc-relative addressing for that label, as in does for all labels
  1371.  ;       when a program is assembled in PC-relative mode, that's why the
  1372.  ;       correction for that label was necessary in that program.
  1373.  
  1374.  ;       In the instruction above, pc-relative addressing can be used because
  1375.  ;       that instruction is not relocated by the bulk move.
  1376.  
  1377.  ;       Now, the address that is used in the instruction below is not the
  1378.  ;       relocated address of the variable; the original location of the
  1379.  ;       variable is used.  When you look at the disassembly listing for this
  1380.  ;       program, you will see that the extension longword (not word) contains
  1381.  ;       the actual address of the variable, not a displacement.
  1382.  
  1383.  ;       Of course, in the instruction above, the extension word does contain
  1384.  ;       a displacement, but this displacement remains valid because the
  1385.  ;       instruction is not moved.
  1386.  
  1387.  ; NOTE: Since processor is in supervisor mode, there is no reason to use
  1388.  ;       trap #3 to fetch time.  The 200hz vector can be referenced directly.
  1389.  
  1390.  move.l     $4BA, (a0)           ; Fetch and store start time.
  1391. aut_start:
  1392. reserved:   ds.b  1024           ; Space for loop construction = 1024 bytes.
  1393. aut_end:
  1394.  dbra       d7, aut_start
  1395.  move.l     $4BA, d0             ; Fetch end time.
  1396.  
  1397.  ;****
  1398.  sub.l      start_time, d0       ; Subtract start time from end time.
  1399.  ;****
  1400.  
  1401.  trap       #10                  ; Convert to decimal milliseconds and print.
  1402. print_memory_header:
  1403.  movea.l    memory_header(pc), a0
  1404.  bsr.s      print_string
  1405. print_requisite_memory:
  1406.  move.w     memory(pc), d1       ; Fetch AUT's requisite memory.
  1407.  trap       #4                   ; Returns address of decimal string in A0.
  1408.  bsr.s      print_string
  1409.  lea        header_1(pc), a0     ; Print requisite memory units label.
  1410.  bsr.s      print_string
  1411.  
  1412.  ; See documentation in program TRAP_9P.S.
  1413.  
  1414.  movea.l    _SSP, a7             ; Restore system stack pointer.
  1415.  rte
  1416.  
  1417.  ;
  1418.  ; SUBROUTINES
  1419.  ;
  1420.  
  1421. print_string:         
  1422.  pea        (a0)
  1423.  move.w     #9, -(sp) 
  1424.  trap       #1        
  1425.  addq.l     #6, sp    
  1426.  rts
  1427.  
  1428.  data
  1429. header_1:      dc.b '  bytes',$D,$A,0
  1430.  bss
  1431.  align
  1432. _SSP:          ds.l    1   ; Address of the system stack will be stored here.
  1433. start_time:    ds.l    1   ; Variable for time at start of AUT processing.
  1434. memory:        ds.w    1   ; Variable for AUT's requisite memory.
  1435. time_header:   ds.l    1   ; Points to address of header which is to precede
  1436.                            ; the reported AUT processing time.
  1437. memory_header: ds.l    1   ; Points to address of header which is to precede
  1438.                            ; the reported AUT requisite memory.
  1439. program_end:   ds.l    0
  1440.  end
  1441.  
  1442.  
  1443. TRAP9TST Execution Results With TRAP_9R.PRG Resident.
  1444.  
  1445. These results match those obtained with the PC-relative
  1446. assembled adaptive algorithm.
  1447.  
  1448.    MULU time:                      360  milliseconds
  1449.    MULU requisite memory:            4  bytes
  1450.    Addition time:                  255  milliseconds
  1451.    Addition requisite memory:        8  bytes
  1452.    Shift and add time:             230  milliseconds
  1453.    Shift and add requisite memory:   6  bytes
  1454.  
  1455.  
  1456.      Program 34 is sufficiently similar to program 36 so 
  1457. that most of the documentation for the first serves to 
  1458. document the second; nevertheless, I still want to point out 
  1459. a few important differences between the programs.  Under the 
  1460. label save_heading_addresses, near the beginning of the 
  1461. trap_9_routine, note that the addresses are stored directly 
  1462. to the labels in program 36 using absolute addressing, as 
  1463. opposed to the indirect addressing method used in program 
  1464. 34.  The absolute addressing mode is also used to store the 
  1465. system stack pointer.  But, as you can see, wherever 
  1466. possible, pc-relative addressing is indicated in most of the 
  1467. instructions that contain labels in the source operand.  
  1468. That mode is indicated with the (pc) notation.
  1469.      There is one particular instruction in which I 
  1470. deliberately avoided pc-relative addressing so that I could 
  1471. illustrate a specific advantage of using the absolute 
  1472. addressing mode in the Relocatable assembled adaptive 
  1473. algorithm.  That is the instruction which subtracts the 
  1474. start time from the end time:
  1475.  
  1476.                 sub.l  start_time, d0.
  1477.   
  1478. The instruction has been made conspicuous by the ;**** group 
  1479. being placed before and after it.  Using absolute addressing 
  1480. in this instruction obviates the inconvenience of a 
  1481. correction to access the start_time variable, as was done in 
  1482. program 34.
  1483.   
  1484. Figure 7.4. Disassembly listing of TRAP_9R.PRG as it resides 
  1485. in memory after the initial invocation of the adaptive 
  1486. algorithm.
  1487.  
  1488.  TRAP_9R.PRG After First Invocation
  1489.  
  1490. 01F9FE 47FA04FC         LEA $1FEFC(PC),A3
  1491. 01FA02 97EF0004         SUBA.L 4(A7),A3
  1492. 01FA06 2F3C00000000     MOVE.L #0,-(A7)
  1493. 01FA0C 3F3C0020         MOVE.W #$20,-(A7)
  1494. 01FA10 4E41             TRAP #1
  1495. 01FA12 5C8F             ADDQ.L #6,A7
  1496. 01FA14 2A40             MOVEA.L D0,A5
  1497.  
  1498.  Note that absolute addressing is used in both operands
  1499.  of the instruction that stores the adaptive algorithm's
  1500.  address in the trap #9 vector.
  1501.  
  1502. 01FA16 23FC0001FA360000 MOVE.L #$1FA36,$A4
  1503.        00A4             
  1504. 01FA20 4855             PEA (A5)
  1505. 01FA22 3F3C0020         MOVE.W #$20,-(A7)
  1506. 01FA26 4E41             TRAP #1
  1507. 01FA28 5C8F             ADDQ.L #6,A7
  1508. 01FA2A 3F3C0000         MOVE.W #0,-(A7)
  1509. 01FA2E 2F0B             MOVE.L A3,-(A7)
  1510. 01FA30 3F3C0031         MOVE.W #$31,-(A7)
  1511. 01FA34 4E41             TRAP #1
  1512.  
  1513.  trap_9 routine starts here
  1514.  
  1515. 01FA36 99CB             SUBA.L A3,A4
  1516. 01FA38 23C80001FEF4     MOVE.L A0,$1FEF4
  1517. 01FA3E 23C90001FEF8     MOVE.L A1,$1FEF8
  1518. 01FA44 23CF0001FEEA     MOVE.L A7,$1FEEA
  1519. 01FA4A 4E6F             MOVE.L USP,A7
  1520. 01FA4C 4A15             TST.B (A5)
  1521. 01FA4E 6706             BEQ.S $1FA56
  1522. 01FA50 204D             MOVEA.L A5,A0
  1523. 01FA52 61000480         BSR $1FED4
  1524. 01FA56 207A049C         MOVEA.L $1FEF4(PC),A0
  1525. 01FA5A 61000478         BSR $1FED4
  1526. 01FA5E 4DFA0046         LEA $1FAA6(PC),A6
  1527. 01FA62 360C             MOVE.W A4,D3
  1528. 01FA64 33C30001FEF2     MOVE.W D3,$1FEF2
  1529. 01FA6A 5343             SUBQ.W #1,D3
  1530. 01FA6C 1CDB             MOVE.B (A3)+,(A6)+
  1531. 01FA6E 51CBFFFC         DBRA D3,$1FA6C
  1532. 01FA72 41FA0432         LEA $1FEA6(PC),A0
  1533. 01FA76 43FA0484         LEA $1FEFC(PC),A1
  1534. 01FA7A 93C8             SUBA.L A0,A1
  1535. 01FA7C 3609             MOVE.W A1,D3
  1536. 01FA7E 5943             SUBQ.W #4,D3
  1537. 01FA80 2248             MOVEA.L A0,A1
  1538. 01FA82 93CE             SUBA.L A6,A1
  1539. 01FA84 2A4E             MOVEA.L A6,A5
  1540. 01FA86 30280002         MOVE.W 2(A0),D0
  1541. 01FA8A 2CD8             MOVE.L (A0)+,(A6)+
  1542. 01FA8C D049             ADD.W A1,D0
  1543. 01FA8E 3B400002         MOVE.W D0,2(A5)
  1544. 01FA92 5343             SUBQ.W #1,D3
  1545. 01FA94 1CD8             MOVE.B (A0)+,(A6)+
  1546. 01FA96 51CBFFFC         DBRA D3,$1FA94
  1547. 01FA9A 5347             SUBQ.W #1,D7
  1548. 01FA9C 41FA0450         LEA $1FEEE(PC),A0
  1549. 01FAA0 20B9000004BA     MOVE.L $4BA,(A0)
  1550. 01FAA6 C0FC0005         MULU #5,D0
  1551. 01FAAA 51CFFFFA         DBRA D7,$1FAA6
  1552. 01FAAE 2039000004BA     MOVE.L $4BA,D0
  1553. 01FAB4 90B90001FEEE     SUB.L $1FEEE,D0
  1554. 01FABA 4E4A             TRAP #$A
  1555. 01FABC 207A003E         MOVEA.L $1FAFC(PC),A0
  1556. 01FAC0 6116             BSR.S $1FAD8
  1557. 01FAC2 323A0032         MOVE.W $1FAF6(PC),D1
  1558. 01FAC6 4E44             TRAP #4
  1559. 01FAC8 610E             BSR.S $1FAD8
  1560. 01FACA 41FA0018         LEA $1FAE4(PC),A0
  1561. 01FACE 6108             BSR.S $1FAD8
  1562. 01FAD0 2E790001FEEA     MOVEA.L $1FEEA,A7
  1563. 01FAD6 4E73             RTE
  1564.  
  1565.  print_string subroutine
  1566.  
  1567. 01FAD8 4850             PEA (A0)
  1568. 01FADA 3F3C0009         MOVE.W #9,-(A7)
  1569. 01FADE 4E41             TRAP #1
  1570. 01FAE0 5C8F             ADDQ.L #6,A7
  1571. 01FAE2 4E75             RTS
  1572. 01FAE4 2020             MOVE.L -(A0),D0
  1573. 01FAE6 6279             BHI.S $1FB61
  1574. 01FAE8 7465             MOVEQ #$65,D2
  1575. 01FAEA 730D             DC.W $730D
  1576. 01FAEC 0A000003         EORI.B #3,D0
  1577. 01FAF0 EF40             ASL.W #7,D0
  1578. 01FAF2 00000000         ORI.B #0,D0
  1579. 01FAF6 00040006         ORI.B #6,D4
  1580. 01FAFA DBBF             DC.W $DBBF
  1581. 01FAFC 0006DC25         ORI.B #$25,D6
  1582. 01FB00 00000000         ORI.B #0,D0
  1583. 01FB04 00000000         ORI.B #0,D0
  1584.  
  1585. 01FE9C 00000000         ORI.B #0,D0
  1586. 01FEA0 00000000         ORI.B #0,D0
  1587.  
  1588.  The movable section.  Starting address is $01FEA6
  1589.  
  1590. 01FEA4 000051CF         ORI.B #-$31,D0
  1591. 01FEA8 FBFE             DC.W $FBFE
  1592. 01FEAA 2039000004BA     MOVE.L $4BA,D0
  1593. 01FEB0 90B90001FEEE     SUB.L $1FEEE,D0 ; sub.l start_time, d0
  1594. 01FEB6 4E4A             TRAP #$A
  1595. 01FEB8 207A003E         MOVEA.L $1FEF8(PC),A0
  1596. 01FEBC 6116             BSR.S $1FED4
  1597. 01FEBE 323A0032         MOVE.W $1FEF2(PC),D1
  1598. 01FEC2 4E44             TRAP #4
  1599. 01FEC4 610E             BSR.S $1FED4
  1600. 01FEC6 41FA0018         LEA $1FEE0(PC),A0
  1601. 01FECA 6108             BSR.S $1FED4
  1602. 01FECC 2E790001FEEA     MOVEA.L $1FEEA,A7
  1603. 01FED2 4E73             RTE
  1604. 01FED4 4850             PEA (A0)
  1605. 01FED6 3F3C0009         MOVE.W #9,-(A7)
  1606. 01FEDA 4E41             TRAP #1
  1607. 01FEDC 5C8F             ADDQ.L #6,A7
  1608. 01FEDE 4E75             RTS
  1609. 01FEE0 2020             MOVE.L -(A0),D0
  1610. 01FEE2 6279             BHI.S $1FF5D
  1611. 01FEE4 7465             MOVEQ #$65,D2
  1612. 01FEE6 730D             DC.W $730D
  1613. 01FEE8 0A000003         EORI.B #3,D0
  1614. 01FEEC EF40             ASL.W #7,D0
  1615. 01FEEE 00000000         ORI.B #0,D0
  1616. 01FEF2 00040006         ORI.B #6,D4
  1617. 01FEF6 DBBF             DC.W $DBBF
  1618. 01FEF8 0006DC25         ORI.B #$25,D6
  1619.    
  1620.  
  1621.      I don't know if I've mentioned it before, but even if I 
  1622. have, it is worth pointing out again that the addresses and 
  1623. the instructions contained therin are not displayed in 
  1624. disassembly listings as neat as one might like.  If you 
  1625. refer to the disassembly listing just above this paragraph 
  1626. you can see that the address for the variable _SSP, 01FEEA, 
  1627. is not displayed.  To locate the contents of that address, 
  1628. it is necessary to locate the nearest address that is 
  1629. displayed.  In this case, that is address 01FEE8.  There you 
  1630. see that the byte stored in that address is the ASCII code 
  1631. for a linefeed.  Then, displayed on the same line, at 
  1632. address 01FEE9 is the 00 byte inserted by the align pseudo-
  1633. op.  Finally, also displayed on the same line, at address 
  1634. 01FEEA, is the first byte of the value stored in _SSP.  That 
  1635. byte is 00.  The next byte of _SSP, at address 01FEEB, is 03 
  1636. and is displayed on that same line.  To locate the other two 
  1637. bytes stored in _SSP one must look at the next line, which 
  1638. is address 01FEEC.
  1639.      The value stored in the variable start_time is neatly 
  1640. displayed on the next line, at address 01FEEE, but on the 
  1641. line following, at address 01FEF2, the first word displayed 
  1642. is the contents of the variable memory, while the second 
  1643. word shown on that line is the first word of the value 
  1644. stored in time_header (address = 01FEF4).  The second word 
  1645. of time-header is displayed on the line labeled 01FEF6.  The 
  1646. last address, 01FEF8, is the variable memory_header.  After 
  1647. a while, you get used to all of this, but I wanted to take 
  1648. the opportunity to mention something that is trivial once 
  1649. you know the "secret", but which can be a source of 
  1650. consternation to one who is not accoustomed to reading the 
  1651. listings.
  1652.      To the extent that the major difference between the PC-
  1653. relative version and the Relocatable version of the custom 
  1654. trap is the addressing mode used in particular instructions, 
  1655. it seems reasonable to question the advantages, or 
  1656. disadvantages, of each addressing mode.  One advantage of 
  1657. absolute addressing has already been discussed: it relieves 
  1658. one of the address correction burden in some instances.  
  1659. Naturally, there is the 16 bit displacement limitation 
  1660. attached to pc-relative addressing, but I find this to be 
  1661. rather insignificant for two reasons.  I don't write many 
  1662. assembly language programs in which instructions and labels 
  1663. are 32,767 bytes apart, and when I do, I can find ways to 
  1664. circumvent that limitation.
  1665.      In maintaining the theme of the book, however, it seems 
  1666. prudent to compare the execution speed and requisite memory 
  1667. for instructions using the two addressing modes when that 
  1668. 16-bit limitation of pc-relative addressing is neglected.  
  1669. Program 37 was designed to yield the appropriate comparative 
  1670. data for this discussion, and, in addition, to serve as a 
  1671. vehicle to illustrate possible consequences of the 
  1672. disruptive modification phenomenon previously mentioned.
  1673.  
  1674. Program 37.  A program that compares the execution speed and 
  1675. requisite memory of two algorithms that write data to a 
  1676. location.
  1677.  
  1678.  ; Program Name: LEA_MOVE.S
  1679.  ;      Version: 1.003
  1680.  
  1681.  ; Assembly Instructions:
  1682.  
  1683.  ;    Assemble in Relocatabe mode and save with a TOS extension.
  1684.  
  1685.  ; Program Function:
  1686.  
  1687.  ;    Compares the relative speed and memory requirements of
  1688.  
  1689.  ;                      lea     label(pc), Am
  1690.  ;                      move.l  An, (Am)
  1691.  
  1692.  ;    and               lea     label, Am
  1693.  ;                      move.l  An, (Am)
  1694.  
  1695.  ;    to                move.l  An, label
  1696.  
  1697.  ; The execution time reported is for 50,000 executions of each algorithm.
  1698.  
  1699.  ;    In addition, this program's first AUT can disrupt the adaptive algorithm
  1700.  ; because the address that is loaded in register A2 depends on the displacement
  1701.  ; between the instruction "lea label(pc), a2" and the label it references.
  1702.  
  1703.  ;    When that instruction is executed in the adaptive algorithm, whatever
  1704.  ; address is the "displacement" distance away from the instruction will be
  1705.  ; loaded into register A2.  Then the instruction following, "move.l a0, (a2)
  1706.  ; will write whatever is in register A0 into that memory location.
  1707.  
  1708.  ;    If the address stored in register A2 while the AUT is being executed by
  1709.  ; the adaptive algorithm happens to be within the adaptive algorithm's program
  1710.  ; or data space, the results could be unpleasant.
  1711.  
  1712.  ;    In fact, an undisciplined store of this type is capable of corrupting any
  1713.  ; instruction or data that happens to be separated from the LEA instruction by
  1714.  ; an amount equal to the displacement, and the results could be catastrophic.
  1715.   
  1716. calculate_program_size:
  1717.  lea        -$102(pc), a1       ; Fetch basepage start address.
  1718.  lea        program_end, a0     ; Fetch program end = array address.
  1719.  trap       #6                  ; Return unused memory to op system.
  1720.  lea        stack, a7
  1721.  
  1722. initialize_registers_1:
  1723.  lea        header_1, a0       
  1724.  lea        header_2, a1
  1725.  lea        lea_move_start, a3
  1726.  lea        lea_move_end, a4
  1727.  lea        heading, a5
  1728.  move.w     #50000, d7
  1729.  trap       #9
  1730.  
  1731. initialize_registers_2:
  1732.  lea        header_3, a0       
  1733.  lea        header_4, a1
  1734.  lea        long_lea_start, a3
  1735.  lea        long_lea_end, a4
  1736.  lea        heading, a5
  1737.  move.b     #0, (a5)            ; Store a NULL in first byte to create a
  1738.  move.w     #50000, d7          ; null string so that heading gets printed
  1739.  trap       #9                  ; only once.
  1740.  
  1741. initialize_registers_3:
  1742.  lea        header_5, a0       
  1743.  lea        header_6, a1
  1744.  lea        move_start, a3
  1745.  lea        move_end, a4
  1746.  lea        heading, a5
  1747.  move.w     #50000, d7     
  1748.  trap       #9             
  1749.  
  1750. terminate:
  1751.  trap       #8
  1752.  
  1753. lea_move_start:                  ; This algorithm is potentially nocuous to
  1754.  lea        label(pc), a2        ; the adaptive algorithm because a displacement 
  1755.  move.l     a0, (a2)             ; will be stored in A2, not an address.
  1756. lea_move_end:
  1757.  
  1758. long_lea_start:                  ; This algorithm poses no threat because an
  1759.  lea        label, a2            ; address in this program's data area will be
  1760.  move.l     a0, (a2)             ; stored in A2.
  1761. long_lea_end:
  1762.  
  1763. move_start:                      ; This algorithm poses no threat because an
  1764.  move.l     a0, label            ; address in this program's data area will be
  1765. move_end:                        ; stored in A2.
  1766.          
  1767.  data
  1768. heading:      dc.b       "LEA_MOVE Program Results",$D,$A,$D,$A,0
  1769. header_1:     dc.b       "  Elapsed time for lea    label(pc), Am ",$D,$A
  1770.               dc.b       "                   move.l An, (Am):      ",0
  1771. header_2:     dc.b       "  Memory required for first algorithm:      ",0
  1772. header_3:     dc.b $D,$A,"  Elapsed time for lea    label, Am ",$D,$A
  1773.               dc.b       "                   move.l An, (Am):      ",0
  1774. header_4:     dc.b       "  Memory required for second algorithm:     ",0
  1775. header_5:     dc.b $D,$A,"  Elapsed time for move.l An, label:     ",0
  1776. header_6:     dc.b       "  Memory required for third algorithm:      ",0
  1777.  bss
  1778.  align
  1779. label:        ds.l  1
  1780.               ds.l 96
  1781. stack:        ds.l  0
  1782. program_end:  ds.l  0 
  1783.  end
  1784.  
  1785.  
  1786.      Before proceeding with the discussion initiated above, 
  1787. I want to show you the alterations that I made to the 
  1788. TRAPS.S program so that the adaptive algorithm would be 
  1789. installed automatically during boot.  First, I renamed the 
  1790. trap installation program from TRAPS.S to CUSTOM.S, then I 
  1791. inserted the TRAP_9P.S program into that source file before 
  1792. assembling the entire conglomeration as CUSTOM.PRG.  I don't 
  1793. want to repeat the entire CUSTOM.S source file, therefore, I 
  1794. have listed only the relevant portions in figure 7.5.
  1795.   
  1796. Figure 7.5. Alterations to TRAPS.S to convert it to 
  1797. CUSTOM.S.  The listing below is the contents of a file 
  1798. called CUSTOM.DOC.  The listing shows only the changes that 
  1799. must be made to TRAPS.S to convert it to CUSTOM.S.  Of 
  1800. course, the alterations to TRAPS.S can be made by copying 
  1801. the contents of CUSTOM.DOC to that file using a suitable 
  1802. editor, such as TEMPUS or 1ST WORD PLUS.
  1803.  
  1804.  
  1805.  ; Program Name: CUSTOM.S 
  1806.  ; Version 1.006
  1807.  
  1808.  ; Algorithms for trap #9, the intelligent algorithm, and trap #10 are included,
  1809.  ; along with the other custom traps from the TRAPS.S program.
  1810.  
  1811.  ; Assembly Instructions:
  1812.  
  1813.  ;    Assemble in PC-relative mode and save with a PRG extension.
  1814.  
  1815. install_trap_9_routine:         ; Note: pointer = vector = pointer.
  1816.  lea        trap_9_routine, a0  ; Fetch address of trap #9 routine.
  1817.  move.l     a0, $A4             ; Store custom trap address in pointer.
  1818.  
  1819. trap_9_routine:
  1820.  
  1821.  ; NOTE: You may want to execute a program that invokes this trap from the
  1822.  ;       AssemPro debugger and single step through the trap instructions, or
  1823.  ;       you many want to set breakpoints and use the "Run program" button to
  1824.  ;       execute to a breakpoint.  It the exercise of this latter option that
  1825.  ;       can cause problems.  If you want to set a breakpoint at an instruction
  1826.  ;       that occurs before the "reserved space", no precautions need be taken,
  1827.  ;       except that you must realize that you could halt at a position after
  1828.  ;       the start time has been initialized, and the execution time will be
  1829.  ;       accumulating during the halt.
  1830.  
  1831.  ;       But, if you want to set a breakpoint at at an instruction that occurs
  1832.  ;       after the "reserved space", you should not do so until the instructions
  1833.  ;       that perform the bulk move have been executed.  If you set a breakpoint
  1834.  ;       at an instruction in the program space which follows the "reserved
  1835.  ;       space" and then execute the bulk move instructions, the breakpoint you
  1836.  ;       have set will cause an illegal command error.
  1837.  
  1838.  ; This custom trap must be invoked by a program which contains one or more
  1839.  ; algorithms for which performance data, in the form of execution time and
  1840.  ; requisite memory, is desired.  The trap must be invoked once for each 
  1841.  ; algorithm under test (AUT).  The trap is intended to be a performance 
  1842.  ; report generator so that performance data for specific algorithms can be
  1843.  ; compared.
  1844.  
  1845.  ; If the program invoking the trap is spawned by SPAWN.TTP, the performance
  1846.  ; data will be printed to a file that is created by SPAWN.TTP.  The name of
  1847.  ; the file will be the name of the spawned program with a DAT suffix.
  1848.  
  1849.  ; If the program invoking the trap is executed from the desktop, the 
  1850.  ; performance data will be printed to the screen.
  1851.  
  1852.  ; The AUT can be assembled in PC-relative or Relocatable mode.
  1853.  
  1854.  ; The custom trap expects the following parameters to be contained in the
  1855.  ; specified registers prior to invocation:
  1856.  
  1857.  ; A0 = The address of a null terminated header to precede the reported
  1858.  ;      AUT execution time.
  1859.  
  1860.  ; A1 = The address of a null terminated header to precede the reported
  1861.  ;      AUT requisite memory.
  1862.  
  1863.  ; A3 = The starting address of an algorith containing one or more instructions.
  1864.  ;      This algorithm becomes the AUT upon invocation of the trap.
  1865.  
  1866.  ; A4 = The ending address of the AUT.
  1867.  
  1868.  ; A5 = At the initial invocation by a specific program, A5 is expected to
  1869.  ;      contain the address of a null terminated heading that is a brief
  1870.  ;      description of the data that is to be reported by the trap.  During
  1871.  ;      all subsequent invocations by that program, A5 must contain the
  1872.  ;      address of a null string.
  1873.  
  1874.  ; D7 = A word length decimal value which specifies the number of times the
  1875.  ;      the AUT is to be executed in a loop in order to generate the execution
  1876.  ;      time data.  Register D7 is the only register which cannot be used by
  1877.  ;      the AUT.  That's because D7 is used as the AUT execution loop counter.
  1878.  
  1879.  ; The custom trap uses the information passed in A3, A4 and D7 to construct
  1880.  ; a loop around the AUT.  The loop is executed the number of times specified
  1881.  ; in register D7.  The time required to execute the loop is calculated and
  1882.  ; printed along with the AUT's requisite memory.
  1883.  
  1884.  ; How Trap #9 Works:
  1885.  
  1886.  ;     The custom trap is an intelligent, self-modifying algorithm.  Prior
  1887.  ; to an initial invocation, the trap #9 routine is composed of three sections.
  1888.  ; The first section contains instructions which are permanently located.  The
  1889.  ; second section is a 1,024 byte block of reserved space into which the AUT
  1890.  ; and the third section is to be copied.  The third section contains the custom
  1891.  ; trap instructions that must be copied so that the first instruction in the
  1892.  ; third section immediately follows the last instruction of the algorithm
  1893.  ; under test.  The size that I chose for the reserved space was arbitrary.
  1894.    
  1895.  ;     After an invocation, the custom trap calculates the number of bytes in
  1896.  ; the algorithm under test.  Then it initializes register D7 for the AUT's
  1897.  ; execution loop.  After saving the addresses of the headers that were passed
  1898.  ; as parameters so that the registers in which they were passed can be used
  1899.  ; by trap #9 and/or the algorithm under test, the trap prints the AUT's
  1900.  ; primary heading and the execution time header.  Then it copies the AUT into
  1901.  ; the reserved space.
  1902.  
  1903.  ;     After the AUT has been copied into the reserved space, the instructions
  1904.  ; and data in the third section of the custom trap are moved into immediate
  1905.  ; proximity of the AUT so that the first instruction of section three follows
  1906.  ; immediately after the last instruction of the algorithm under test.
  1907.  
  1908.  ;     The AUT is executed the number of times requested via the value passed
  1909.  ; in D7, then the execution time and requisite memory of the AUT are printed.
  1910.  
  1911.  ;     After the custom trap has been invoked once, the reserved space will
  1912.  ; not be completely clear during the remaining portion of the power-up cycle.
  1913.  ; When the trap is subsequently invoked, the instructions that are already in
  1914.  ; the reserved space will simply be overwritten by the instructions of the
  1915.  ; new algorithm under test and those of the third section.
  1916.  
  1917. calculate_length_of_AUT:
  1918.  suba.l     a3, a4               ; Subtract start address from end address.
  1919.  
  1920. save_heading_addresses:
  1921.  lea        time_header, a2      ; Header to precede reported execution time.
  1922.  move.l     a0, (a2)            
  1923.  lea        memory_header, a2    ; Header to precede reported requisite memory.
  1924.  move.l     a1, (a2)           
  1925.  
  1926. transfer_stack_pointer:
  1927.  
  1928.  ; Upon entrance into this custom trap, A7 contains the address of the system
  1929.  ; stack pointer.  Because the system stack may be too short for use by the AUT,
  1930.  ; the invoking program must provide a user stack, and, here, I am going to
  1931.  ; store the address of that stack in A7.  Before returning to the invoking
  1932.  ; program, the system stack pointer must be restored so that the return address
  1933.  ; can be found by the processor.
  1934.  
  1935.  lea        _SSP, a0             ; Fetch address of declared variable.
  1936.  move.l     a7, (a0)             ; Save system stack pointer.
  1937.  move       USP, a7              ; Transfer to invoking program's stack.
  1938.  
  1939. print_heading:
  1940.  
  1941.  ; NOTE: When two or more algorithms are to invoke the trap from a program,
  1942.  ;       the heading should be printed only once, at the beginning of the
  1943.  ;       report; therefore, the string address in A5 should point to a
  1944.  ;       null terminated string during the first invocation of the trap, but
  1945.  ;       it should point to a null string on subsequent invocations from the
  1946.  ;       same program.
  1947.  
  1948.  ;       For that reason, the test for NULL string is included below, so that
  1949.  ;       only one attempt to print the heading will be made.
  1950.  
  1951.  tst.b      (a5)                 ; NULL string test.
  1952.  beq.s      print_time_header    ; Branch if null.
  1953.  movea.l    a5, a0               ; Print heading.
  1954.  bsr        print_string_9
  1955.  
  1956. print_time_header:
  1957.  movea.l    time_header, a0      ; Fetch address of time header.
  1958.  bsr        print_string_9
  1959.  
  1960. build_algorithm:
  1961.  lea        reserved_space, a6   ; Fetch address of reserved space.
  1962.  move.w     a4, d3               ; AUT length initializes counter for copy.
  1963.  lea        memory, a0           ; Store AUT's requisite memory.
  1964.  move.w     d3, (a0)             ; AUT length stored for report.
  1965.  subq.w     #1, d3               ; Initialize counter for loop execution.
  1966. move_loop:                       ; Move AUT, byte by byte, to the area
  1967.  move.b     (a3)+, (a6)+         ; declared as "reserved_space".
  1968.  dbra       d3, move_loop        ; Branch until D3 = -1.
  1969.  
  1970.  ; A6 is now pointing to the location at which the AUT execution loop's DBRA
  1971.  ; instruction must be copied.  The DBRA copy must be processed apart from the
  1972.  ; other instructions in the custom trap which must be copied to "close up" the
  1973.  ; gap between the last statement of the algorithm under test and the rest
  1974.  ; of the custom trap's instructions.
  1975.  
  1976.  lea        algorithm_end, a0    ; Calculate number of bytes in this program
  1977.  lea        trap_9_end, a1       ; which must be copied into "reserved_space",
  1978.  suba.l     a0, a1               ; then initialize counter D3 with the number
  1979.  move.w     a1, d3               ; of bytes to copy.
  1980.  subq.w     #4, d3               ; Subtract the DBRA requisite memory.
  1981.  movea.l    a0, a1               ; Calculate amount the DBRA instruction must
  1982.  suba.l     a6, a1               ; be moved and save the new location in scratch
  1983.  movea.l    a6, a5               ; register for displacement correction.
  1984.  move.w     2(a0), d0            ; Fetch current DBRA displacement value.
  1985.  move.l     (a0)+, (a6)+         ; Move the DBRA instruction.
  1986.  add.w      a1, d0               ; Correct DBRA displacement to the value it
  1987.  move.w     d0, 2(a5)            ; should be after the move.
  1988.  subq.w     #1, d3               ; Initialize counter for bulk copy.
  1989. _move_loop:                      ; Move rest of algorithm in a bulk copy.
  1990.  move.b     (a0)+, (a6)+
  1991.  dbra       d3, _move_loop
  1992.  subq.w     #1, d7               ; Initialize D7 for AUT loop execution.
  1993.  lea        start_time, a0       ; Fetch address of declared variable.
  1994.  suba.l     a1, a0               ; Correct address to after-move location.
  1995.  
  1996.  ; NOTE: Since processor is in supervisor mode, there is no reason to use
  1997.  ;       trap #3 to fetch time.  The 200hz vector can be referenced directly.
  1998.  
  1999.  move.l     $4BA, (a0)           ; Fetch and store start time.
  2000. algorithm_start:
  2001. reserved_space:  ds.b  1024      ; Space for loop construction = 1024 bytes.
  2002. algorithm_end:
  2003.  dbra       d7, algorithm_start
  2004.  move.l     $4BA, d0             ; Fetch end time.
  2005.  sub.l      start_time, d0       ; Subtract start time from end time.
  2006.  trap       #10                  ; Convert to decimal milliseconds and print.
  2007. print_memory_header:
  2008.  movea.l    memory_header, a0    ; Fetch address of memory header.
  2009.  bsr        print_string_9
  2010. print_requisite_memory:
  2011.  move.w     memory, d1           ; Fetch AUT's requisite memory.
  2012.  trap       #4                   ; Returns address of decimal string in A0.
  2013.  bsr        print_string_9
  2014.  lea        header_1, a0         ; Print requisite memory units label.
  2015.  bsr        print_string_9
  2016.  
  2017.  ; NOTE:  I had thought that I might have to restore the user stack pointer
  2018.  ;        before returning to the calling program because I can't know to what
  2019.  ;        extent the AUT has corrupted the user stack.
  2020.  
  2021.  ;        But, as it turns out, since the value in USP is stored in register
  2022.  ;        A7 at the beginning of the program, and since the system stack pointer
  2023.  ;        is then active and remains so for the duration of the trap invocation,
  2024.  ;        only the value in register A7 (which is the system stack pointer, but
  2025.  ;        which points to the user stack) is altered; the value in USP remains
  2026.  ;        uncorrupted, therefore, nothing needs be restored but the system stack
  2027.  ;        pointer (so that it again points to the system stack).
  2028.  
  2029.  ;        On subsequent invocations the value in USP, which remains stable, will
  2030.  ;        simply be restored in A7, as often as the trap is invoked.
  2031.  
  2032.  movea.l    _SSP, a7             ; Restore system stack pointer so that it
  2033.  rte                             ; points to the system stack.
  2034.  
  2035. trap_9_data_and_subroutine:
  2036.  
  2037.  ; NOTE: Trap #9 must have its own print_string subroutine because the
  2038.  ;       displacements in the bsr print_string instructions in trap #9 are
  2039.  ;       not altered by the move of this section into the reserved space.
  2040.  
  2041.  ;       Therefore, the displacement between the instructions and the
  2042.  ;       print_string subroutine must remained constant.  The only way to
  2043.  ;       maintain the displacement (without corrections) is to move the
  2044.  ;       subroutine along with the rest of this section.
  2045.  
  2046.  ;       Then what happens is this: the bsr print_string instructions located
  2047.  ;       above the reserved space cause a branch to the pre-move location of the
  2048.  ;       subroutine; those instructions located below the reserved space cause
  2049.  ;       a branch to the after-move location of the subroutine.  If you say all
  2050.  ;       of this to yourself very quickly, it is less confusing.  I think.
  2051.  
  2052. print_string_9:                 ; Expects address of string to be in A0.
  2053.  pea        (a0)                ; Push address of string onto stack.
  2054.  move.w     #9, -(sp)           ; Function = c_conws = GEMDOS $9.
  2055.  trap       #1                  ; GEMDOS call
  2056.  addq.l     #6, sp              ; Reset stack pointer to top of stack.
  2057.  rts
  2058.   
  2059. header_1:      dc.b '  bytes',$D,$A,0
  2060.  align
  2061. _SSP:          ds.l    1   ; Address of the system stack will be stored here.
  2062. start_time:    ds.l    1   ; Variable for time at start of AUT processing.
  2063. memory:        ds.w    1   ; Variable for AUT's requisite memory.
  2064. time_header:   ds.l    1   ; Points to address of header which is to precede
  2065.                            ; the reported AUT processing time.
  2066. memory_header: ds.l    1   ; Points to address of header which is to precede
  2067.                            ; the reported AUT requisite memory.
  2068. trap_9_end:    ds.l    1   ; Marks end of trap #9 section.
  2069.  
  2070.  ; This statement and the items in boldface below are not part of the trap_9
  2071.  ; routine.  They are there to provide orientation so that the appropriate
  2072.  ; sections of this document may be copied into the new CUSTOM.S document.
  2073.  
  2074. trap_10_routine:
  2075.  
  2076. print_string:                   ; Expects address of string to be in A0.
  2077.  pea        (a0)                ; Push address of string onto stack.
  2078.  move.w     #9, -(sp)           ; Function = c_conws = GEMDOS $9.
  2079.  trap       #1                  ; GEMDOS call
  2080.  addq.l     #6, sp              ; Reset stack pointer to top of stack.
  2081.  rts
  2082.  
  2083.  data
  2084. subtrahend:       dc.l   $3B9ACA00,$5F5E100,$989680,$F4240,$186A0,$2710
  2085.                   dc.l   $3E8,$64,$A,$1,$0
  2086. hex_table:        dc.b   '0123456789ABCDEF'
  2087. spawned:          dc.b   $0
  2088. space:            dc.b   " ",0
  2089.  
  2090. units_label:      dc.b   "  milliseconds", $D,$A,0
  2091.  
  2092.  bss
  2093.  align                       ; Align storage on a word boundary.
  2094. after_load_time:  ds.w   1   ; Spawned program's after load time. 
  2095. decimal:          ds.l   3   ; Output buffer.  Must be NULL terminated.
  2096. hexadecimal:      ds.l   3   ; Output buffer.  Must be NULL terminated.
  2097.  
  2098. program_end:      ds.l   0
  2099.  end      
  2100.  
  2101.  
  2102.      The execution results of program 37 are shown in figure 
  2103. 7.6.  The data illustrates that there is no speed nor 
  2104. requisite memory difference between the first and third 
  2105. algorithms.  The addressing modes used in those algorithms 
  2106. is pc-relative for the first and absolute for the third.  
  2107. The first algorithm may seem to be hampered by the extra 
  2108. instruction needed to indirectly store the data in An, but 
  2109. it is only when pc-relative addressing cannot be used with 
  2110. the LEA instruction that the extra instruction becomes a 
  2111. handicap.  This is evident from the data for the second 
  2112. algorithm, where the execution time and requisite memory are 
  2113. greater than that for the other two algorithms.  But, in 
  2114. general, the algorithms being considered will be those with 
  2115. the appearance of algorithms one and two.  Clearly, the 
  2116. execution speed and requisite memory of those are identical.
  2117.  
  2118. Figure 7.6. Execution results of program 37 with the newly 
  2119. created CUSTOM.PRG resident.
  2120.  
  2121. LEA_MOVE Program Results
  2122.  
  2123.   Elapsed time for lea    label(pc), Am 
  2124.                    move.l An, (Am):        205  milliseconds
  2125.   Memory required for first algorithm:       6  bytes
  2126.  
  2127.   Elapsed time for lea    label, Am 
  2128.                    move.l An, (Am):        235  milliseconds
  2129.   Memory required for second algorithm:      8  bytes
  2130.  
  2131.   Elapsed time for move.l An, label:       205  milliseconds
  2132.   Memory required for third algorithm:       6  bytes
  2133.  
  2134.  
  2135.      A partial disassembly of the adaptive algorithm during 
  2136. invocation, but before AUT loop execution, by each of 
  2137. program 37's three AUT's is shown in figure 7.7.  Although 
  2138. the addresses here are different than those shown in 
  2139. previous disassembly listings, because the custom trap was 
  2140. installed by CUSTOM.PRG during boot, it is easy to see that 
  2141. the displacement in the extension word of the first AUT's 
  2142. LEA instruction causes an address to be loaded into A2 that 
  2143. is not located in the invoking program, but is located 
  2144. within the custom trap's space.  No problem occurs because 
  2145. it just so happens that the address $17D54 falls within the 
  2146. unused reserved space.  But the folly of depending on this 
  2147. kind of luck should be apparent.  This problem does not 
  2148. occur with the second and third AUTs because relative 
  2149. addressing is not used in those instructions; therefore the 
  2150. address loaded into A2 during invocation by the second and 
  2151. third AUTs is located within the invoking program's address 
  2152. space.
  2153.   
  2154. Figure 7.7. A partial disassembly of the adaptive algorithm 
  2155. during invocation by program 37's three AUTs.
  2156.  
  2157.  LEA_MOVE's 1st AUT in CUSTOM's adaptive
  2158.  
  2159. 017BCA 45FA0188         LEA $17D54(PC),A2
  2160. 017BCE 2488             MOVE.L A0,(A2)
  2161. 017BD0 51CFFFF8         DBRA D7,$17BCA
  2162.  
  2163.  LEA_MOVE's 2nd AUT in CUSTOM's adaptive
  2164.  
  2165. 017BCA 45F90006D730     LEA $6D730,A2
  2166. 017BD0 2488             MOVE.L A0,(A2)
  2167. 017BD2 51CFFFF6         DBRA D7,$17BCA
  2168.  
  2169.  LEA_MOVE's 3rd AUT in CUSTOM's adaptive
  2170.  
  2171. 017BCA 23C80006D730     MOVE.L A0,$6D730
  2172. 017BD0 51CFFFF8         DBRA D7,$17BCA
  2173.  
  2174.  
  2175.      I must not leave you with the impression that the 
  2176. problem with the address being loaded in the first AUT has 
  2177. much to do with the fact that it is not located within the 
  2178. boundaries of the invoking program.  No, it is because the 
  2179. address it does load is within the boundaries of the 
  2180. adaptive algorithm and that address is going to be corrupted 
  2181. by the second statement of the first algorithm.  The purpose 
  2182. of the three AUT's is to compare the execution speed and 
  2183. requisite memory of three algorithms which store data in an 
  2184. address that is specified by a label.  As far as the test is 
  2185. concerned, the location of the label can be anyplace in 
  2186. memory.
  2187.      Of course, I would not leave you to suffer this 
  2188. dilemma.  I have prepared another version of program 37 and 
  2189. another version of the adaptive algorithm to illustrate a 
  2190. method of dealing with this problem of referencing labels in 
  2191. an AUT's data area from within the execution loop located in 
  2192. the adaptive algorithm.  Program 38 is the program that will 
  2193. exercise the new adaptive algorithm.  AUT_DATA's execution 
  2194. results are shown in figure 7.8.
  2195.  
  2196. Program 38. In this program, data areas are declared for 
  2197. each AUT, and the variables label_1, label_2 and label_3 are 
  2198. the labels for those data areas.
  2199.  
  2200.  ; Program Name: AUT_DATA.S
  2201.  ;      Version: 1.001
  2202.  
  2203.  ; Assembly Instructions:
  2204.  
  2205.  ;    Assemble in Relocatabe mode and save with a TOS extension.
  2206.  
  2207.  ; Program Function:
  2208.  
  2209.  ;    Compares the relative speed and memory requirements of
  2210.  
  2211.  ;                      lea     label(pc), Am
  2212.  ;                      move.l  An, (Am)
  2213.  
  2214.  ;    and               lea     label, Am
  2215.  ;                      move.l  An, (Am)
  2216.  
  2217.  ;    to                move.l  An, label
  2218.  
  2219.  ; The execution time reported is for 50,000 executions of each algorithm.
  2220.  
  2221.  ;    In this program, a data area is declared before the AUT's so that the
  2222.  ; first AUT can't disrupt the adaptive algorithm.  The address of the data
  2223.  ; area is passed to the adaptive algorithm in register A2.
  2224.  
  2225.  ;    A branch statement is included in each AUT so that the adaptive algorithm
  2226.  ; will jump over the data area.
  2227.   
  2228.  ;    Of course, this calls for a redesign of the adaptive algorithm.
  2229.  
  2230. calculate_program_size:
  2231.  lea        -$102(pc), a1       ; Fetch basepage start address.
  2232.  lea        program_end, a0     ; Fetch program end = array address.
  2233.  trap       #6                  ; Return unused memory to op system.
  2234.  lea        stack, a7
  2235.  
  2236. initialize_registers_1:
  2237.  lea        header_1, a0       
  2238.  lea        header_2, a1
  2239.  lea        lea_data_area, a2
  2240.  lea        lea_move_start, a3
  2241.  lea        lea_move_end, a4
  2242.  lea        heading, a5
  2243.  move.w     #50000, d7
  2244.  trap       #9
  2245.  
  2246. initialize_registers_2:
  2247.  lea        header_3, a0       
  2248.  lea        header_4, a1
  2249.  lea        long_data_area, a2
  2250.  lea        long_lea_start, a3
  2251.  lea        long_lea_end, a4
  2252.  lea        heading, a5
  2253.  move.b     #0, (a5)            ; Store a NULL in first byte to create a
  2254.  move.w     #50000, d7          ; null string so that heading gets printed
  2255.  trap       #9                  ; only once.
  2256.  
  2257. initialize_registers_3:
  2258.  lea        header_5, a0       
  2259.  lea        header_6, a1
  2260.  lea        move_data_area, a2
  2261.  lea        move_start, a3
  2262.  lea        move_end, a4
  2263.  lea        heading, a5
  2264.  move.w     #50000, d7     
  2265.  trap       #9             
  2266.  
  2267. terminate:
  2268.  trap       #8
  2269.  
  2270. lea_data_area:
  2271.  bra.s      lea_move_start
  2272. label_1:    ds.l 1
  2273. lea_move_start:                
  2274.  lea        label_1(pc), a2      
  2275.  move.l     a0, (a2)           
  2276. lea_move_end:
  2277.  
  2278. long_data_area:
  2279.  bra.s      long_lea_start
  2280. label_2:    ds.l 1
  2281. long_lea_start:              
  2282.  lea        label_2, a2        
  2283.  move.l     a0, (a2)         
  2284. long_lea_end:
  2285.  
  2286. move_data_area:
  2287.  bra.s      move_start
  2288. label_3:    ds.l 1
  2289. move_start:                  
  2290.  move.l     a0, label_3        
  2291. move_end:                    
  2292.          
  2293.  data
  2294. heading:      dc.b       "AUT_DATA Program Results",$D,$A,$D,$A,0
  2295. header_1:     dc.b       "  Elapsed time for lea    label(pc), Am ",$D,$A
  2296.               dc.b       "                   move.l An, (Am):      ",0
  2297. header_2:     dc.b       "  Memory required for first algorithm:      ",0
  2298. header_3:     dc.b $D,$A,"  Elapsed time for lea    label, Am ",$D,$A
  2299.               dc.b       "                   move.l An, (Am):      ",0
  2300. header_4:     dc.b       "  Memory required for second algorithm:     ",0
  2301. header_5:     dc.b $D,$A,"  Elapsed time for move.l An, label:     ",0
  2302. header_6:     dc.b       "  Memory required for third algorithm:      ",0
  2303.  bss
  2304.  align
  2305.               ds.l 96
  2306. stack:        ds.l  0
  2307. program_end:  ds.l  0 
  2308.  end
  2309.  
  2310.   
  2311. Program 39. A new version of the program that installs the 
  2312. adaptive algorithm.  This version is designed to process 
  2313. AUT's in which an area of memory has been set aside to be 
  2314. used as a data area.  Note that the pseudo-op data is not 
  2315. used.
  2316.  
  2317.  ; Program Name: TRAP9DAT.S
  2318.  ; Version 1.002
  2319.  
  2320.  ; Assembly Instructions:
  2321.  
  2322.  ;    Assemble in PC-relative mode and save with a PRG extension.
  2323.  
  2324.  ; Program Function:
  2325.  
  2326.  ;    This is a LSR program that establishes a user defined trap #9.  It may
  2327.  ; be executed from the desktop, but you may prefer to copy it to the AUTO
  2328.  ; folder of your boot partition or floppy disk so that it will execute
  2329.  ; automatically during boot.
  2330.  
  2331.  ;    This is a special, single-purpose trap that is used to illustrate a
  2332.  ; method of preventing corruption of the adaptive algorithm.
  2333.  
  2334. program_start:                  ; Calculate program size and retain result.
  2335.  lea        program_end, a3     ; Fetch program end address.
  2336.  suba.l     4(a7), a3           ; Subtract basepage address.
  2337.  
  2338. enter_supervisor_mode:
  2339.  move.l     #0, -(sp)           ; The zero turns on supervisor mode.
  2340.  move.w     #$20, -(sp)         ; Function = super = GEMDOS $20.
  2341.  trap       #1                  ; Supervisor stack pointer (SSP) returned in D0.
  2342.  addq.l     #6, sp             
  2343.  movea.l    d0, a5              ; Save SSP in scratch register.
  2344.  
  2345. install_trap_9_routine:         ; Note: pointer = vector = pointer.
  2346.  lea        trap_9_routine, a0  ; Fetch address of trap #9 routine.
  2347.  move.l     a0, $A4             ; Store trap address at pointer address.
  2348.  
  2349. enter_user_mode:
  2350.  pea        (a5)                ; Restore supervisor stack pointer.
  2351.  move.w     #$20, -(sp)         ; Function = super = GEMDOS $20.
  2352.  trap       #1
  2353.  addq.l     #6, sp 
  2354.  
  2355. relinquish_processor_control:   ; Maintain memory residency.
  2356.  move.w    #0, -(sp)            ; Exit code. 
  2357.  move.l    a3, -(sp)            ; Program size.
  2358.  move.w    #$31, -(sp)          ; Function = ptermres = GEMDOS $31.
  2359.  trap      #1
  2360.  
  2361. trap_9_routine:
  2362.  
  2363.  ; The custom trap expects the following parameters to be contained in the
  2364.  ; specified registers prior to invocation:
  2365.  
  2366.  ; A0 = The address of a null terminated header to precede the reported
  2367.  ;      AUT execution time.
  2368.  
  2369.  ; A1 = The address of a null terminated header to precede the reported
  2370.  ;      AUT requisite memory.
  2371.  
  2372.  ; A2 = The address of a data area for the algorithm to be tested.  The ending
  2373.  ;      address for the data area must be the address stored in register A3; 
  2374.  ;      that is, it must be the starting address for the algorithm.
  2375.  
  2376.  ; A3 = The starting address of an algorithm containing one or more instructions.
  2377.  ;      This algorithm becomes the AUT upon invocation of the trap.
  2378.  
  2379.  ; A4 = The ending address of the AUT.
  2380.  
  2381.  ; A5 = At the initial invocation by a specific program, A5 is expected to
  2382.  ;      contain the address of a null terminated heading that is a brief
  2383.  ;      description of the data that is to be reported by the trap.  During
  2384.  ;      all subsequent invocations by that program, A5 must contain the
  2385.  ;      address of a null string.
  2386.  
  2387.  ; D7 = A word length decimal value which specifies the number of times the
  2388.  ;      the AUT is to be executed in a loop in order to generate the execution
  2389.  ;      time data.  Register D7 is the only register which cannot be used by
  2390.  ;      the AUT.  That's because D7 is used as the AUT execution loop counter.
  2391.  
  2392. calculate_length_of_AUT_plus_data_area:
  2393.  suba.l     a2, a4               ; Subtract data start address from AUT start
  2394.                                  ; address.
  2395. calculate_length_of_AUT_data_area:
  2396.  suba.l     a2, a3               ; Subtract AUT start address from AUT end
  2397.                                  ; address.
  2398. save_heading_addresses:
  2399.  lea        time_header, a6      ; Header to precede reported execution time.
  2400.  move.l     a0, (a6)
  2401.  lea        memory_header, a6    ; Header to precede reported requisite memory.
  2402.  move.l     a1, (a6)
  2403.  lea        heading, a6          ; Null terminated heading or NULL string.
  2404.  move.l     a5, (a6)
  2405.  
  2406. transfer_AUT_start_address:      ; Because contents of A2 will be altered soon.
  2407.  movea.l    a2, a5
  2408.  
  2409. transfer_stack_pointer:
  2410.  lea        _SSP, a0             ; Fetch address of declared variable.
  2411.  move.l     a7, (a0)             ; Save system stack pointer.
  2412.  move       USP, a7              ; Transfer to invoking program's stack.
  2413.  
  2414. print_heading:
  2415.  movea.l    heading, a0          ; Fetch heading address.
  2416.  tst.b      (a0)                 ; NULL string test.
  2417.  beq.s      print_time_header    ; Branch if null.
  2418.  bsr        print_string
  2419.  
  2420. print_time_header:
  2421.  movea.l    time_header, a0      ; Fetch address of time header.
  2422.  bsr        print_string
  2423.  
  2424. move_AUT:
  2425.  lea        reserved_space, a6   ; Fetch address of reserved space.
  2426.  move.w     a4, d3               ; AUT length initializes counter for copy.
  2427.  lea        memory, a0           ; Store AUT's requisite memory.
  2428.  move.w     d3, d0               ; Copy total AUT length to D0 for correction.
  2429.  sub.w      a3, d0               ; Subtract length of data area.
  2430.  move.w     d0, (a0)             ; AUT length stored for report.
  2431.  subq.w     #1, d3               ; Initialize counter for loop execution.
  2432. move_loop:                       ; Move data area and AUT, byte by byte, to the
  2433.  move.b     (a5)+, (a6)+         ; area declared as "reserved_space".
  2434.  dbra       d3, move_loop        ; Branch until D3 = -1.
  2435.  
  2436. move_adaptive_algorithm:
  2437.  lea        algorithm_end, a0    ; Calculate number of bytes in this program
  2438.  lea        program_end, a1      ; which must be copied into "reserved_space",
  2439.  suba.l     a0, a1               ; then initialize counter D3 with the number
  2440.  move.w     a1, d3               ; of bytes to copy.
  2441.  subq.w     #4, d3               ; Subtract the DBRA requisite memory.
  2442.  movea.l    a0, a1               ; Calculate amount the DBRA instruction must
  2443.  suba.l     a6, a1               ; be moved and save the new location in scratch
  2444.  movea.l    a6, a5               ; register for displacement correction.
  2445.  move.w     2(a0), d0            ; Fetch current DBRA displacement value.
  2446.  move.l     (a0)+, (a6)+         ; Move the DBRA instruction.
  2447.  
  2448.  ; In this version of the adaptive algorithm, when the DBRA displacement is
  2449.  ; corrected, the size of the AUT's data space must be added to the
  2450.  ; correction so that the branch will go to the start of the AUT's executable
  2451.  ; statements, not to the start of the data space.
  2452.  
  2453.  add.w      a3, d0               ; Add length of AUT's data space.
  2454.  add.w      a1, d0               ; Correct DBRA displacement to the value it
  2455.  move.w     d0, 2(a5)            ; should be after the move.
  2456.  subq.w     #1, d3               ; Initialize counter for bulk copy.
  2457. _move_loop:                      ; Move rest of algorithm in a bulk copy.
  2458.  move.b     (a0)+, (a6)+
  2459.  dbra       d3, _move_loop
  2460.  subq.w     #1, d7               ; Initialize D7 for AUT loop execution.
  2461.  lea        start_time, a0       ; Fetch address of declared variable.
  2462.  suba.l     a1, a0               ; Correct address to after-move location.
  2463.  
  2464.  ; NOTE: Since processor is in supervisor mode, there is no reason to use
  2465.  ;       trap #3 to fetch time.  The 200hz vector can be referenced directly.
  2466.  
  2467.  move.l     $4BA, (a0)           ; Fetch and store start time.
  2468. algorithm_start:
  2469. reserved_space:  ds.b  1024      ; Space for loop construction = 1024 bytes.
  2470. algorithm_end:
  2471.  dbra       d7, algorithm_start
  2472.  move.l     $4BA, d0             ; Fetch end time.
  2473.  sub.l      start_time, d0       ; Subtract start time from end time.
  2474.  trap       #10                  ; Convert to decimal milliseconds and print.
  2475. print_memory_header:
  2476.  movea.l    memory_header, a0    ; Fetch address of memory header.
  2477.  bsr.s      print_string
  2478. print_requisite_memory:
  2479.  move.w     memory, d1           ; Fetch AUT's requisite memory.
  2480.  trap       #4                   ; Returns address of decimal string in A0.
  2481.  bsr.s      print_string
  2482.  lea        header_1, a0         ; Print requisite memory units label.
  2483.  bsr.s      print_string
  2484.  movea.l    _SSP, a7             ; Restore system stack pointer so that it
  2485.  rte                             ; points to the system stack.
  2486.  
  2487.  ;
  2488.  ; SUBROUTINES
  2489.  ;
  2490.  
  2491. print_string:         
  2492.  pea        (a0)
  2493.  move.w     #9, -(sp) 
  2494.  trap       #1        
  2495.  addq.l     #6, sp    
  2496.  rts
  2497.  
  2498.  data
  2499. header_1:      dc.b '  bytes',$D,$A,0
  2500.  bss
  2501.  align
  2502. _SSP:          ds.l    1   ; Address of the system stack will be stored here.
  2503. start_time:    ds.l    1   ; Variable for time at start of AUT processing.
  2504. memory:        ds.w    1   ; Variable for AUT's requisite memory.
  2505. time_header:   ds.l    1   ; Points to address of header which is to precede
  2506.                            ; the reported AUT processing time.
  2507. memory_header: ds.l    1   ; Points to address of header which is to precede
  2508.                            ; the reported AUT requisite memory.
  2509. heading:       ds.l    1   ; Null terminated heading or NULL string.
  2510. program_end:   ds.l    0
  2511.  end
  2512.  
  2513.  
  2514. Figure 7.8. AUT_DATA's execution results.
  2515.  
  2516. AUT_DATA Program Results
  2517.  
  2518.   Elapsed time for lea    label(pc), Am 
  2519.                    move.l An, (Am):        205  milliseconds
  2520.   Memory required for first algorithm:       6  bytes
  2521.  
  2522.   Elapsed time for lea    label, Am 
  2523.                    move.l An, (Am):        230  milliseconds
  2524.   Memory required for second algorithm:      8  bytes
  2525.  
  2526.   Elapsed time for move.l An, label:       205  milliseconds
  2527.   Memory required for third algorithm:       6  bytes
  2528.  
  2529.  
  2530. Figure 7.9. Disassembly listing.  The first section is a 
  2531. complete listing of the adaptive algorithm during invocation 
  2532. by the first AUT.  Only partial listings are shown for the 
  2533. invocations by the second and third AUTs.  All listings were 
  2534. prepared before execution of the adaptive algorithm's 
  2535. performance loop.
  2536.  
  2537.  AUT_DATA's 1st AUT in TRAP9DAT
  2538.  
  2539. 01FA36 99CA             SUBA.L A2,A4
  2540. 01FA38 97CA             SUBA.L A2,A3
  2541. 01FA3A 4DFA04C4         LEA $1FF00(PC),A6
  2542. 01FA3E 2C88             MOVE.L A0,(A6)
  2543. 01FA40 4DFA04C2         LEA $1FF04(PC),A6
  2544. 01FA44 2C89             MOVE.L A1,(A6)
  2545. 01FA46 4DFA04C0         LEA $1FF08(PC),A6
  2546. 01FA4A 2C8D             MOVE.L A5,(A6)
  2547. 01FA4C 2A4A             MOVEA.L A2,A5
  2548. 01FA4E 41FA04A6         LEA $1FEF6(PC),A0
  2549. 01FA52 208F             MOVE.L A7,(A0)
  2550. 01FA54 4E6F             MOVE.L USP,A7
  2551. 01FA56 207A04B0         MOVEA.L $1FF08(PC),A0
  2552. 01FA5A 4A10             TST.B (A0)
  2553. 01FA5C 6704             BEQ.S $1FA62
  2554. 01FA5E 61000480         BSR $1FEE0
  2555. 01FA62 207A049C         MOVEA.L $1FF00(PC),A0
  2556. 01FA66 61000478         BSR $1FEE0
  2557. 01FA6A 4DFA004C         LEA $1FAB8(PC),A6
  2558. 01FA6E 360C             MOVE.W A4,D3
  2559. 01FA70 41FA048C         LEA $1FEFE(PC),A0
  2560. 01FA74 3003             MOVE.W D3,D0
  2561. 01FA76 904B             SUB.W A3,D0
  2562. 01FA78 3080             MOVE.W D0,(A0)
  2563. 01FA7A 5343             SUBQ.W #1,D3
  2564. 01FA7C 1CDD             MOVE.B (A5)+,(A6)+
  2565. 01FA7E 51CBFFFC         DBRA D3,$1FA7C
  2566. 01FA82 41FA0434         LEA $1FEB8(PC),A0
  2567. 01FA86 43FA0484         LEA $1FF0C(PC),A1
  2568. 01FA8A 93C8             SUBA.L A0,A1
  2569. 01FA8C 3609             MOVE.W A1,D3
  2570. 01FA8E 5943             SUBQ.W #4,D3
  2571. 01FA90 2248             MOVEA.L A0,A1
  2572. 01FA92 93CE             SUBA.L A6,A1
  2573. 01FA94 2A4E             MOVEA.L A6,A5
  2574. 01FA96 30280002         MOVE.W 2(A0),D0
  2575. 01FA9A 2CD8             MOVE.L (A0)+,(A6)+
  2576. 01FA9C D04B             ADD.W A3,D0
  2577. 01FA9E D049             ADD.W A1,D0
  2578. 01FAA0 3B400002         MOVE.W D0,2(A5)
  2579. 01FAA4 5343             SUBQ.W #1,D3
  2580. 01FAA6 1CD8             MOVE.B (A0)+,(A6)+
  2581. 01FAA8 51CBFFFC         DBRA D3,$1FAA6
  2582. 01FAAC 5347             SUBQ.W #1,D7
  2583.  
  2584. 01FAAE 41FA044A         LEA $1FEFA(PC),A0
  2585. 01FAB2 91C9             SUBA.L A1,A0
  2586. 01FAB4 20B804BA         MOVE.L $4BA,(A0)
  2587. 01FAB8 6004             BRA.S $1FABE
  2588. 01FABA 00000000         ORI.B #0,D0
  2589. 01FABE 45FAFFFA         LEA $1FABA(PC),A2
  2590. 01FAC2 2488             MOVE.L A0,(A2)
  2591. 01FAC4 51CFFFF8         DBRA D7,$1FABE
  2592. 01FAC8 203804BA         MOVE.L $4BA,D0
  2593. 01FACC 90BA0038         SUB.L $1FB06(PC),D0
  2594.  
  2595. 01FAD0 4E4A             TRAP #$A
  2596. 01FAD2 207A003C         MOVEA.L $1FB10(PC),A0
  2597. 01FAD6 6114             BSR.S $1FAEC
  2598. 01FAD8 323A0030         MOVE.W $1FB0A(PC),D1
  2599. 01FADC 4E44             TRAP #4
  2600. 01FADE 610C             BSR.S $1FAEC
  2601. 01FAE0 41FA0016         LEA $1FAF8(PC),A0
  2602. 01FAE4 6106             BSR.S $1FAEC
  2603. 01FAE6 2E7A001A         MOVEA.L $1FB02(PC),A7
  2604. 01FAEA 4E73             RTE
  2605. 01FAEC 4850             PEA (A0)
  2606. 01FAEE 3F3C0009         MOVE.W #9,-(A7)
  2607. 01FAF2 4E41             TRAP #1
  2608. 01FAF4 5C8F             ADDQ.L #6,A7
  2609. 01FAF6 4E75             RTS
  2610. 01FAF8 2020             MOVE.L -(A0),D0
  2611. 01FAFA 6279             BHI.S $1FB75
  2612. 01FAFC 7465             MOVEQ #$65,D2
  2613. 01FAFE 730D             DC.W $730D
  2614. 01FB00 0A000004         EORI.B #4,D0
  2615. 01FB04 0EB000000000     BCLR #0,0(A0,D0.W)
  2616. 01FB0A 00060006         ORI.B #6,D6
  2617. 01FB0E FB75             DC.W $FB75
  2618. 01FB10 0006FBC9         ORI.B #-$37,D6
  2619. 01FB14 0006FB58         ORI.B #$58,D6
  2620. 01FB18 040A             DC.W $40A
  2621. 01FB1A 00000000         ORI.B #0,D0
  2622. 01FB1E 00000000         ORI.B #0,D0
  2623.  
  2624. 01FEAE 00000000         ORI.B #0,D0
  2625. 01FEB2 00000000         ORI.B #0,D0
  2626. 01FEB6 000051CF         ORI.B #-$31,D0
  2627. 01FEBA FBFE             DC.W $FBFE 
  2628. 01FEBC 203804BA         MOVE.L $4BA,D0
  2629. 01FEC0 90BA0038         SUB.L $1FEFA(PC),D0
  2630. 01FEC4 4E4A             TRAP #$A
  2631. 01FEC6 207A003C         MOVEA.L $1FF04(PC),A0
  2632. 01FECA 6114             BSR.S $1FEE0
  2633. 01FECC 323A0030         MOVE.W $1FEFE(PC),D1
  2634. 01FED0 4E44             TRAP #4
  2635. 01FED2 610C             BSR.S $1FEE0
  2636. 01FED4 41FA0016         LEA $1FEEC(PC),A0
  2637. 01FED8 6106             BSR.S $1FEE0
  2638. 01FEDA 2E7A001A         MOVEA.L $1FEF6(PC),A7
  2639. 01FEDE 4E73             RTE
  2640. 01FEE0 4850             PEA (A0)
  2641. 01FEE2 3F3C0009         MOVE.W #9,-(A7)
  2642. 01FEE6 4E41             TRAP #1
  2643. 01FEE8 5C8F             ADDQ.L #6,A7
  2644. 01FEEA 4E75             RTS
  2645. 01FEEC 2020             MOVE.L -(A0),D0
  2646. 01FEEE 6279             BHI.S $1FF69
  2647. 01FEF0 7465             MOVEQ #$65,D2
  2648. 01FEF2 730D             DC.W $730D
  2649. 01FEF4 0A000004         EORI.B #4,D0
  2650. 01FEF8 0EB000000000     BCLR #0,0(A0,D0.W)
  2651. 01FEFE 00060006         ORI.B #6,D6
  2652. 01FF02 FB75             DC.W $FB75
  2653. 01FF04 0006FBC9         ORI.B #-$37,D6
  2654. 01FF08 0006FB58         ORI.B #$58,D6
  2655.  
  2656.  AUT_DATA's 2nd AUT in TRAP9DAT
  2657.  
  2658. 01FAAE 41FA044A         LEA $1FEFA(PC),A0
  2659. 01FAB2 91C9             SUBA.L A1,A0
  2660. 01FAB4 20B804BA         MOVE.L $4BA,(A0)
  2661. 01FAB8 6004             BRA.S $1FABE
  2662. 01FABA 00000000         ORI.B #0,D0
  2663. 01FABE 45F90006FB40     LEA $6FB40,A2
  2664. 01FAC4 2488             MOVE.L A0,(A2)
  2665. 01FAC6 51CFFFF6         DBRA D7,$1FABE
  2666. 01FACA 203804BA         MOVE.L $4BA,D0
  2667.  
  2668.  AUT_DATA's 3rd AUT in TRAP9DAT
  2669.  
  2670. 01FAAE 41FA044A         LEA $1FEFA(PC),A0
  2671. 01FAB2 91C9             SUBA.L A1,A0
  2672. 01FAB4 20B804BA         MOVE.L $4BA,(A0)
  2673. 01FAB8 6004             BRA.S $1FABE
  2674. 01FABA 00000000         ORI.B #0,D0
  2675. 01FABE 23C80006FB4E     MOVE.L A0,$6FB4E
  2676. 01FAC4 51CFFFF8         DBRA D7,$1FABE
  2677. 01FAC8 203804BA         MOVE.L $4BA,D0
  2678.  
  2679.  
  2680.      In figure 7.9, you can see that only in the performance 
  2681. loop for the first AUT does the AUT reference an address 
  2682. that is located within the adaptive algorithm's space.  The 
  2683. instructions in the other two AUT's reference an address 
  2684. that is located within the invoking program's space.  
  2685. Knowing how the declared data space will be referenced, you 
  2686. can choose the addressing mode that forces the reference to 
  2687. be performed in the manner most suited to specific 
  2688. applications.  The most important difference between this 
  2689. adaptive algorithm and the previous is that this one permits 
  2690. instructions to write to a data area without disrupting the 
  2691. adaptive algorithm.
  2692.  
  2693. Wrapping It Up
  2694.  
  2695.      I am going to wrap up this chapter with two more 
  2696. comparative programs.  Both programs were executed after the 
  2697. custom traps were installed with CUSTOM.PRG.  Program 40 was 
  2698. designed to confirm or refute the statement on page 113 of 
  2699. the Stan Kelly-Bootie book which asserts that MOVEA.Z 
  2700. #<label>, A0 is equivalent to LEA <label>, A0, and faster.  
  2701. Program 40 should be assembled in PC-relative mode, saved 
  2702. with a TOS extension; then the name of the file should be 
  2703. changed to LEAMOVER in the assempro editor, and that file 
  2704. should be assembled in Relocatable mode.  Figure 7.10 shows 
  2705. the results of LEAMOVEA.TOS; figure 7.11 shows those of 
  2706. LEAMOVER.TOS.
  2707.  
  2708. Program 40. A program that compares the execution speed and 
  2709. requisite memory of two instructions that load an address 
  2710. into an address register.
  2711.   
  2712.  ; Program Name: LEAMOVEA.S
  2713.  ;      Version: 1.001
  2714.  
  2715.  ; Assembly Instructions:
  2716.  
  2717.  ;    Assemble with ASSEMPRO and save with a TOS extension.
  2718.  
  2719.  ; Execution Instructions:
  2720.  
  2721.  ;     Execute from the desktop; or execute SPAWN.TTP, type LEAMOVEA.TOS on
  2722.  ; its command line and view this program's output in LEAMOVEA.DAT.
  2723.  
  2724.  ; Program Function:
  2725.  
  2726.  ;    Confirms (or refutes) the statement on page 113 of the Stan Kelly-
  2727.  ; Bootle book, to wit: MOVEA.Z #<label>, A0 is equivalent to LEA, and
  2728.  ; faster.
  2729.  
  2730.  ;    For each of the two methods of loading the address of a string into
  2731.  ; and address register, calculates the memory occupied by each method, and
  2732.  ; calculates the execution time in milliseconds required for 50,000
  2733.  ; executions of each.
  2734.  
  2735.  ; PROGRAM RESULTS:
  2736.  
  2737.  ;      When the program containing the two instructions under discussion
  2738.  ; is assembled in AssemPro's Relocatable mode, the instructions are
  2739.  ; equivalent in speed and requisite memory.
  2740.  
  2741.  ;      However, when the program is assembled in AssemPro's PC-relative
  2742.  ; mode, the LEA instruction is faster and requires less memory.  The claim
  2743.  ; that the MOVEA.Z instruction is faster than the LEA instruction is,
  2744.  ; therefore, soundly refuted.
  2745.  
  2746.  ;      But, when the program is assembled in PC-relative mode, the MOVEA.Z
  2747.  ; instruction does not move the correct value into the address register,
  2748.  ; so there is really no choice when either pc-relative addressing or
  2749.  ; PC-relative assembly is used--LEA must be used then.
  2750.  
  2751. calculate_program_size:
  2752.  lea        -$102(pc), a1       ; Fetch basepage start address.
  2753.  lea        program_end, a0     ; Fetch program end = array address.
  2754.  trap       #6                  ; Return unused memory to op system.
  2755.  lea        stack, a7
  2756.  
  2757. initialize_registers_1:
  2758.  lea        header_1, a0       
  2759.  lea        header_2, a1
  2760.  lea        lea_start, a3
  2761.  lea        lea_end, a4
  2762.  lea        heading, a5
  2763.  move.w     #50000, d7
  2764.  trap       #9
  2765.  
  2766. initialize_registers_2:
  2767.  lea        header_3, a0       
  2768.  lea        header_4, a1
  2769.  lea        movea_start, a3
  2770.  lea        movea_end, a4
  2771.  lea        heading, a5
  2772.  move.b     #0, (a5)            ; Store a NULL in first byte to create a
  2773.  move.w     #50000, d7          ; null string so that heading gets printed
  2774.  trap       #9                  ; only once.
  2775.  
  2776. terminate:
  2777.  trap       #8
  2778.  
  2779. lea_start:
  2780.  lea        newline, a2         ; Instruction in the loop.
  2781. lea_end:
  2782.  
  2783. movea_start:
  2784.  movea.l     #newline, a2       ; Instruction in the loop.
  2785. movea_end:
  2786.  
  2787.  data
  2788. heading:      dc.b       'LEAMOVEA Execution Results',$D,$A,$D,$A,0
  2789. header_1:     dc.b       '  Elapsed time for LEA:    ',0
  2790. header_2:     dc.b       '  Memory required for LEA:    ',0
  2791. header_3:     dc.b $D,$A,'  Elapsed time for MOVEA:  ',0
  2792. header_4:     dc.b       '  Memory required for MOVEA:  ',0
  2793. newline:      dc.b $D,$A,0
  2794.  bss
  2795.  align
  2796.               ds.l 96
  2797. stack:        ds.l  0
  2798. program_end:  ds.l  0
  2799.  end
  2800.  
  2801.   
  2802. Figure 7.10. Execution results for LEAMOVEA.TOS.
  2803.  
  2804. LEAMOVEA Execution Results
  2805.  
  2806.   Elapsed time for LEA:      130  milliseconds
  2807.   Memory required for LEA:     4  bytes
  2808.  
  2809.   Elapsed time for MOVEA:    155  milliseconds
  2810.   Memory required for MOVEA:   6  bytes
  2811.   
  2812.   
  2813. Figure 7.11. Execution results for LEAMOVER.TOS.
  2814.  
  2815. LEAMOVER Execution Results
  2816.  
  2817.   Elapsed time for LEA:      155  milliseconds
  2818.   Memory required for LEA:     6  bytes
  2819.  
  2820.   Elapsed time for MOVEA:    155  milliseconds
  2821.   Memory required for MOVEA:   6  bytes
  2822.   
  2823.   
  2824.      The data shown in figure 7.11 confirms that the 
  2825. execution speed and requisite memory for the two 
  2826. instructions are equivalent when the program in which they 
  2827. reside is assembled in the Relocatable mode.  However, the 
  2828. data in figure 7.10 shows that when the program is assembled 
  2829. in PC-relative mode, or when pc-relative addressing is used 
  2830. in the source operand of the LEA instruction, that 
  2831. instruction is faster and uses less memory.
  2832.      But there is more to this comparison then is readily 
  2833. apparent.  Figure 7.12 is a partial disassembly of the 
  2834. adaptive algorithm during invocation of the two PC-relative 
  2835. AUT's.  There you can see the futility and danger of trying 
  2836. to use the movea instruction to load an address in a PC-
  2837. relative assembled program.  The address that is actually 
  2838. loaded is located beyond the space of both the invoking 
  2839. program and the adaptive algorithm.  Figure 7.13 shows that 
  2840. either instruction can be used to load an address that is 
  2841. located within the invoking algorithm's space.
  2842.  
  2843. Figure 7.12. Partial disassembly of the adaptive algorithm 
  2844. during invocation by the two AUT's in LEAMOVEA.TOS.
  2845.  
  2846.  LEAMOVEA.TOS partial disassembly in trap
  2847.  
  2848.  LEAMOVEA.TOS was prepared by assembling LEAMOVEA.S in AssemPro's PC-relative
  2849.  mode.  The address being loaded into A2 by the LEA instruction is located
  2850.  within the space of the adaptive algorithm.
  2851.  
  2852. 017BCA 45FA009F         LEA $17C6B(PC),A2
  2853. 017BCE 51CFFFFA         DBRA D7,$17BCA
  2854.  
  2855.  The address being loaded into A2 by the MOVEA instruction decimal 233 and is
  2856.  located beyond the space of the adaptive algorithm and that of the invoking
  2857.  program.
  2858.  
  2859. 017BCA 247C000000E9     MOVEA.L #$E9,A2
  2860. 017BD0 51CFFFF8         DBRA D7,$17BCA
  2861.  
  2862.   
  2863. Figure 7.13. Partial disassembly of the adaptive algorithm 
  2864. during invocation by the two AUT's in LEAMOVER.TOS.
  2865.  
  2866.  LEAMOVER.TOS partial disassembly in trap
  2867.  
  2868.  LEAMOVER.TOS was prepared by assembling LEAMOVEA.S in AssemPro's Relocatable
  2869.  mode.  The address being loaded into A2 by the LEA instruction is located
  2870.  within the space of the invoking algorithm.
  2871.  
  2872. 017BCA 45F90006D6AF     LEA $6D6AF,A2
  2873. 017BD0 51CFFFF8         DBRA D7,$17BCA
  2874.  
  2875.  The address being loaded into A2 by the MOVEA instruction is located within
  2876.  the space of the invoking algorithm.
  2877.  
  2878. 017BCA 247C0006D6AF     MOVEA.L #$6D6AF,A2
  2879. 017BD0 51CFFFF8         DBRA D7,$17BCA
  2880.  
  2881.   
  2882.      Based on the data produced and shown in figures 7.10, 
  2883. 7.11, 7.12 and 7.13, I conclude that Mr. Kelly-Bootle's 
  2884. claim is soundly refuted, and furthermore, when the program 
  2885. in which the instructions reside is assembled in PC-relative 
  2886. mode, the MOVEA instruction does not move the correct value 
  2887. into the address register, so there is really no choice when 
  2888. either pc-relative addressing or PC-relative assembly is 
  2889. used.  In either of those two cases, the LEA instruction 
  2890. must be used.
  2891.  
  2892. Just One More, I Promise
  2893.  
  2894.      Program 41 compares pea (a0) to move.l a0, -(sp).  I am 
  2895. including this program for two reasons.  The first reason is 
  2896. to confirm that they are equivalent; the second is to give 
  2897. you an example of the kind of information that is contained 
  2898. in the Thomas P. Skinner book--the kind of information that 
  2899. prompted me to recommend it.  The results of program 41's 
  2900. execution follow the listing.  Personally, I think that the 
  2901. PEA instruction is the more elegant.
  2902.  
  2903. Program 41. Compares two ways of pushing the contents 
  2904. of an address register onto the stack.    
  2905.   
  2906.  ; Program Name: PEA_MOVE.S
  2907.  ;      Version: 1.001
  2908.  
  2909.  ; Assembly Instructions:
  2910.  
  2911.  ;    Assemble in PC-relative mode and save with a TOS extension.
  2912.  
  2913.  ; Program Function:
  2914.  
  2915.  ;    Compares the relative speed and memory requirements of "pea (a0)" to
  2916.  ; that of "move.l a0, -(sp)".  The execution time reported is for
  2917.  ; 50,000 executions of each instruction.
  2918.  
  2919.  ; Execution Note:
  2920.  
  2921.  ;    Invokes traps that are installed by CUSTOM.PRG during boot.
  2922.  
  2923. calculate_program_size:
  2924.  lea        -$102(pc), a1       ; Fetch basepage start address.
  2925.  lea        program_end, a0     ; Fetch program end = array address.
  2926.  adda.l     #200512, a0         ; Add in extra large stack space.
  2927.  movea.l    a0, a7              ; Point A7 to this program's stack.
  2928.  trap       #6                  ; Return unused memory to op system.
  2929.  
  2930. initialize_registers_1:
  2931.  lea        header_1, a0       
  2932.  lea        header_2, a1
  2933.  lea        pea_algorithm_start, a3
  2934.  lea        pea_algorithm_end, a4
  2935.  lea        heading, a5
  2936.  move.w     #50000, d7
  2937.  trap       #9
  2938.  
  2939. initialize_registers_2:
  2940.  lea        header_3, a0       
  2941.  lea        header_4, a1
  2942.  lea        move_algorithm_start, a3
  2943.  lea        move_algorithm_end, a4
  2944.  lea        heading, a5
  2945.  move.b     #0, (a5)            ; Store a NULL in first byte to create a
  2946.  move.w     #50000, d7          ; null string so that heading gets printed
  2947.  trap       #9                  ; only once.
  2948.  
  2949. terminate:
  2950.  trap       #8
  2951.  
  2952. pea_algorithm_start:
  2953.  pea        (a0)                ; Instruction in the loop.
  2954. pea_algorithm_end:
  2955.  
  2956. move_algorithm_start:
  2957.  move.l     a0, -(sp)           ; Instruction in the loop.
  2958. move_algorithm_end:
  2959.          
  2960.  data
  2961. heading:      dc.b       "PEA_MOVE Program Results",$D,$A,$D,$A,0
  2962. header_1:     dc.b       "  Elapsed time for pea (a0):         ",0
  2963. header_2:     dc.b       "  Memory required for pea (a0):         ",0
  2964. header_3:     dc.b $D,$A,"  Elapsed time for move.l a0, -(sp): ",0
  2965. header_4:     dc.b       "  Memory for move.l a0, -(sp)           ",0
  2966.  bss
  2967.  align                       
  2968. program_end:  ds.l  0 
  2969.  end
  2970.  
  2971. PEA_MOVE Program Results
  2972.  
  2973.   Elapsed time for pea (a0):           155  milliseconds
  2974.   Memory required for pea (a0):          2  bytes
  2975.  
  2976.   Elapsed time for move.l a0, -(sp):   155  milliseconds
  2977.   Memory for move.l a0, -(sp)            2  bytes
  2978.   
  2979.  
  2980. Conclusion
  2981.  
  2982.      The thrust of this chapter was twofold.  First, I 
  2983. wanted to present an algorithm that would permit shorter 
  2984. versions of programs designed to obtain performance or 
  2985. comparative data.  Second, in doing that, I wanted to 
  2986. illustrate the inherent power of self-modifying algorithms.  
  2987. There are many more things that I could say about such 
  2988. algorithms, but I can't allow myself to be drawn into that 
  2989. provocative subject--lest I abandon the rest of the book.  I 
  2990. leave you with this thought.  Suppose that you learned to do 
  2991. truly powerful things with your personal computer.  With 
  2992. whom would you share your secrets?  Is it possible that you 
  2993. might even discourage others from traveling the routes that 
  2994. led to your own success?
  2995.  
  2996.